我的服务器/监听器缺少True Grit

时间:2012-01-06 17:18:58

标签: c# sockets

我的服务器/监听器有ADD或没有耐力;什么是解毒剂或产品?

该应用程序充当套接字通信的两端。它似乎适用于第一条消息(我在textBox1中输入“Bla”,然后label1读取“Bla back atcha”,但它在后续消息中失败。我在我的开发机器上运行了一个应用程序实例,另一个实例(在其他计算机上重命名为包含“服务器”一词)。

我已经粘贴了下面的代码,并且错误的消息我第二次尝试发送消息(“因为目标机器主动拒绝它而无法建立连接10.24.93.110:51111").

当我在另一台机器上启动“Server”实例并在命令行中运行“netstat -a”时,它表示服务器机器正在侦听端口51111上的dev机器。

传递第一条消息后,显然收到并抛回,运行“netstat -a”仍显示与我的开发机器的连接,但该状态不再是LISTENING而是TIME_WAIT。

然后,我尝试传递另一条消息,我得到了错误的消息(下面的图表B)

附件A:来源

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();
        }
    }
}

EXHIBIT B:完整错误消息

  

System.Net.Sockets.SocketException未处理     消息=“无法建立连接,因为目标计算机主动拒绝它10.24.93.110:51111”     来源=“系统”     错误码= 10061     NativeErrorCode = 10061     堆栈跟踪:          在System.Net.Sockets.TcpClient..ctor(String hostname,Int32 port)          在testSocketSendAndReceive_Nutshell.Form1.Client()中   C:\ testSocketSendAndReceive_Nutshell \ testSocketSendAndReceive_Nutshell \ Form1.cs:第57行          at testSocketSendAndRendive_Nutshell.Form1.button1_Click(Object sender,EventArgs e)位于C:\ testSocketSendAndReceive_Nutshell \ testSocketSendAndReceive_Nutshell \ Form1.cs:第90行,位于System.Windows.Forms.Control.OnClick(EventArgs e)          在System.Windows.Forms.Button.OnClick(EventArgs e)          在System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)          在System.Windows.Forms.Control.WmMouseUp(消息& m,MouseButtons按钮,Int32点击)          在System.Windows.Forms.Control.WndProc(消息& m)          在System.Windows.Forms.ButtonBase.WndProc(消息& m)          在System.Windows.Forms.Button.WndProc(消息& 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& msg)          在System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID,Int32 reason,Int32 pvLoopData)          在System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32原因,   ApplicationContext context)          在System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason,ApplicationContext)   上下文)          在System.Windows.Forms.Application.Run(Form mainForm)          在testSocketSendAndReceive_Nutshell.Program.Main()中   C:\ testSocketSendAndReceive_Nutshell \ testSocketSendAndReceive_Nutshell \ Program.cs:第18行          在System.AppDomain._nExecuteAssembly(Assembly assembly,String [] args)          在System.AppDomain.ExecuteAssembly(String assemblyFile,Evidence assemblySecurity,String [] args)          在Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()          在System.Threading.ThreadHelper.ThreadStart_Context(对象状态)          在System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback回调,   对象状态)          在System.Threading.ThreadHelper.ThreadStart()     InnerException:

4 个答案:

答案 0 :(得分:3)

查看服务器代码开头的注释

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

这是完全正确的 - 你打电话给AcceptTcpClient一次,回应,然后关闭听众。那只会处理一个连接。如果你想要它处理多个连接,你需要循环 - 很可能在循环并再次接受之前将每个TCP客户端交给一个单独的线程。

答案 1 :(得分:2)

您对Server()方法的评论会回答您自己的问题:

// Handles a single client request, then exits.

读完第一个字符串后,调用listener.Stop()然后从函数返回,以便线程退出。如果您希望服务器为后续请求保持活跃状态​​,那么您将不得不采用某种循环方式。

答案 2 :(得分:2)

在您的服务器上,您在收到第一条消息后正在处理客户端。

如果要保持TCP连接处于活动状态,则需要在服务器方法中保存TCP客户端。然后你可以使用像client.GetStream().Read()这样的方法来读取客户端的数据。请注意,此方法将阻止,直到您从流中收到消息。

为了处理n个请求,你必须做一些循环:

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

还有一些异步方法可以让您在另一个线程上执行这些操作。查看流上的BeginRead()方法。

答案 3 :(得分:1)

发送响应后需要调用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