Моему Серверу / Слушателю не хватает True Grit - PullRequest
1 голос
/ 06 января 2012

Мой сервер / слушатель имеет ADD или нет выносливости;Что такое противоядие или prodote?

Приложение служит обоими концами соединения сокета.Похоже, что это нормально работает для первого сообщения (я ввожу «Bla» в textBox1, а label1 затем читает «Bla back atcha», но это не удается в последующих сообщениях. У меня один экземпляр приложения работает на моем компьютере разработчика, а другойЭкземпляр (переименован, чтобы включить слово «Сервер») на другом компьютере.

Я вставил приведенный ниже код и сообщение об ошибке, которое я получаю при второй попытке отправить сообщение («Невозможно установить соединениепотому что целевая машина активно отказалась от него 10.24.93.110:51111").

Когда я запускаю экземпляр «Server» на другом компьютере и запускаю «netstat -a» в командной строке, он говорит, что серверmachine LISTENING моей машине dev на порту 51111.

После того, как первое сообщение передано, и, очевидно, получено и отброшено, выполнение "netstat -a" все еще показывает соединение с моей машиной dev, но это состояниебольше не LISTENING, а TIME_WAIT.

А затем я пытаюсь передать другое сообщение и получаю сообщение об ошибке (Приложение B ниже)

ПРИЛОЖЕНИЕ A: Source

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Diagnostics;

namespace testSocketSendAndReceive_Nutshell
{
    public partial class Form1 : Form
    {
        string sJerrysIPAddr = "10.24.31.110";
        string sMyIPAddr = "10.24.31.128";
        string sThisAppFileName = string.Empty;
        bool bThisInstanceFunctionsAsServer = false;

        internal static Form1 MainSocketPairForm = null;

        public Form1()
        {
            InitializeComponent();
            MainSocketPairForm = this;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            sThisAppFileName = System.Diagnostics.Process.GetCurrentProcess().ProcessName;
            lblFileName.Text = sThisAppFileName;

            // Client and Server code are here combined in one app; however, we want each instance to run as
            // just one or the other, so (the .exe functioning as a Server should be renamed with the subString
            // "Server" somewhere in the filename):
            bThisInstanceFunctionsAsServer = sThisAppFileName.Contains("Server");
            if (bThisInstanceFunctionsAsServer)
            {
                new Thread(Server).Start();       // Run server method concurrently.
                Thread.Sleep(500);                // Give server time to start.
            }
            btnSendMsg.Visible = !bThisInstanceFunctionsAsServer;
        }

        static void Client()
        {
            using (TcpClient client = new TcpClient(Form1.MainSocketPairForm.sJerrysIPAddr, 51111)) // err here second time 
            using (NetworkStream n = client.GetStream())
            {
                BinaryWriter w = new BinaryWriter(n);
                w.Write(Form1.MainSocketPairForm.textBox1.Text.ToString());
                w.Flush();
                Form1.MainSocketPairForm.label1.Text = new BinaryReader(n).ReadString();
            }
        }

        static void Server()     // Handles a single client request, then exits.
        {
            TcpListener listener = new TcpListener(IPAddress.Any, 51111);
            listener.Start(); //Only one usage of each socket address (protocol/network address/port) is normally permitted
            // got the above err msg with an instance running and listening on jerry's machine
            // continues to listen even after shut down...
            using (TcpClient c = listener.AcceptTcpClient())
            using (NetworkStream n = c.GetStream())
            {
                string msg = new BinaryReader(n).ReadString();
                BinaryWriter w = new BinaryWriter(n);
                w.Write(msg + " back atcha!");
                w.Flush(); // Must call Flush because we're not disposing the writer.
            }
            listener.Stop();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Client();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Close();
        }
    }
}

ПРИМЕР Б: полное сообщение об ошибке

System.Net.Sockets.SocketException is nothandled Message = "Невозможно установить соединение, поскольку целевая машина активно отказала ему 10.24.93.110: 51111 "Source =" System "ErrorCode = 10061 NativeErrorCode = 10061 StackTrace: в System.Net.Sockets.TcpClient..ctor (строковое имя хоста, порт Int32) в testSocketSendAndReceive_Nutshell.Form1.Client () в C: \ testhellDocket_testSocketSendAndReceive_Nutshell \ Form1.cs: строка 57 в testSocketSendAndReceive_Nutshell.Form1.button1_Click (отправитель объекта, EventArgs e) в C: \ testSocketSendAndReceive_Nutshell \ testSocketSendAndReceive_Nutscs.egn.OnC.System.Windows.Forms.Button.OnClick (EventArgs e) в System.Windows.Forms.Button.OnMouseUp (MouseEventArgs mevent) в System.Windows.Forms.Control.WmMouseUp (сообщение & m, кнопка MouseButtons, щелчки Int32) в системе.Windows.Forms.Control.WndProc (Сообщение & m) в System.Windows.Forms.ButtonBase.WndProc (Message & m) в System.Windows.Forms.Button.WndProc (Message & m) в System.Windows.Forms.Control.ControlNativeWindow.OnMessage (Message & m) в System.Windows.Forms.Control.ControlNativeWindow.WndProc (Message & m) в System.Windows.Forms.NativeWindow.DebuggableCallback (IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) в System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW в MSG & MS).Application.ComponentManager.System.Windows.Forms.Application.ThreadContext.RunMessageLoop (причина Int32, контекст ApplicationContext) в System.Windows.Forms.Application.Run (форма mainForm) в testSocketSendAndReceive_Nutshell.Program.Main () в C: \ testSocketSendAndResert_NutsSNestSecurity_Nellhell \ Program.cs: строка 18 в System.AppDomain._nExecuteAssembly (сборка Assembly, аргументы String []) в System.AppDomain.ExecuteAssembly (строка String AssemblyFile, Evidence assemblySecurity, String []) в Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly () в System.Threading.ThreadHelper.ThreadStart_Context (состояние объекта) в System.Threading.ExecutionContext.Run (обратный вызов ExecutionContext executeContext, ContextCallback, состояние объекта) в System.Threading.ThreadHelper.ThreadStart () * InnerException: 1019*

Ответы [ 4 ]

3 голосов
/ 06 января 2012

Посмотрите на комментарий в начале кода вашего сервера

static void Server()     // Handles a single client request, then exits.

Это совершенно правильно - вы вызываете AcceptTcpClient один раз, отвечаете, а затем выключаете слушателя.Это будет обрабатывать только одно соединение.Если вы хотите, чтобы оно обрабатывало более одного соединения, вам нужно выполнить цикл по кругу - вполне возможно передать каждый TCP-клиент отдельному потоку перед циклом и принять снова.

2 голосов
/ 06 января 2012

На вашем сервере вы избавляетесь от клиента после получения первого сообщения.

Если вы хотите сохранить активное TCP-соединение, вам нужно сохранить TCP-клиента в методе сервера. Затем вы можете использовать методы типа client.GetStream().Read(), которые будут считывать данные из клиента. Обратите внимание, что этот метод будет блокироваться, пока вы не получите сообщение из потока.

Чтобы обработать n запросов, вам нужно выполнить какой-то цикл:

while(true) {
   string msg = client.GetStream().Read();
   // do something with the message
}

Существуют также асинхронные методы, которые позволят вам выполнять эти действия в другом потоке. Посмотрите на метод BeginRead() в потоке.

2 голосов
/ 06 января 2012

Ваш комментарий к методу Server() отвечает на ваш собственный вопрос:

// Handles a single client request, then exits.

После того, как вы прочитали первую строку, вы вызываете listener.Stop() и затем возвращаетесь из функции, поэтому поток завершается. Если вы хотите, чтобы сервер оставался активным для последующих запросов, вам придется включить какой-то цикл.

1 голос
/ 06 января 2012

Вам необходимо позвонить client.Close() после отправки ответа. Вы также нуждаетесь в цикле вокруг логики принятия сервера:

var shouldExit == false;
while (!shouldExit)
    using (TcpClient c = listener.AcceptTcpClient())
    {
        using (NetworkStream n = c.GetStream())
        {
            string msg = new BinaryReader(n).ReadString();
            if (msg == "exit")
                // Client told us to exit...
                shouldExit = true;
            BinaryWriter w = new BinaryWriter(n);
            w.Write(msg + " back atcha!");
            w.Flush(); // Must call Flush because we're not disposing the writer.
        }
    }

Это всев примерах в документации: http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...