简体   繁体   English

C#TCP服务器无法响应客户端

[英]C# TCP Server cannot response to client

So my job now is to create a server that can respond and connect to several client at once, that's why I create a threaded server and some test client to check. 因此,我现在的工作是创建一个可以同时响应并连接到多个客户端的服务器,这就是为什么我创建一个线程服务器和一些要检查的测试客户端的原因。

The Client can connect to the server them by pressing a button, it will send a message to the server, the server will put to message to its interface then respond to the client. 客户端可以通过按下按钮将它们连接到服务器,它将向服务器发送一条消息,服务器会将消息放入其界面,然后响应客户端。 Lastly the client will receive the response and put it onto its interface. 最后,客户端将收到响应并将其放入其界面。

The problem I got now is the server can receive the message from the server and display but the response from server to client is not successful even though they are similar. 我现在遇到的问题是服务器可以从服务器接收消息并显示,但是服务器到客户端的响应即使它们相似也不会成功。 From the debugger it seems that the client is stuck at the Read procedure. 从调试器看来,客户端处于“读取”过程。

Below is my code for the server. 下面是我的服务器代码。 I think the problem come at the connection handler and client side. 我认为问题出在连接处理程序和客户端。 I am stuck now, please show me what did I do wrong @@ 我现在被困住了,请告诉我我做错了什么@@

public class Server
{
    TcpListener serverSocket = new TcpListener(IPAddress.Any, 3000);
    TcpClient clientSocket = default(TcpClient);
    int counter = 0;
    private exampleCallback callback;

    public Server(exampleCallback Callback)
    {
        callback = Callback;
    }

    public void initServer()
    {
        serverSocket.Start();

        //Call back to main thread to update display
        if (callback != null)
            callback(">> Server Initialized!");

        Console.WriteLine(">> Server Initialized!");
    }

    public void waitConnection()
    {
        int counter = 0;
        while (true)
        {
            counter += 1;
            clientSocket = serverSocket.AcceptTcpClient();

            if (callback != null)
                callback(">> Client number: " + counter + " started!");

            Console.WriteLine(">> Client number: " + counter + " started!");

            handleClient handerler = new handleClient(new exampleCallback(receiveCallback), clientSocket, counter);
            Thread clientThread = new Thread(new ThreadStart(handerler.startConv));
            clientThread.Start();
        }
    }

    public void closeServer()
    {
        clientSocket.Close();
        serverSocket.Stop();
    }

    private void receiveCallback(string message)
    {
        callback(message);
    }


}

The code for Connection Handerler: 连接处理程序的代码:

public class handleClient
{
    private exampleCallback callback2;
    TcpClient clientSocket;
    int clientNo;

    public handleClient(exampleCallback Callback, TcpClient client, int clNo)
    {
        callback2 = Callback;
        clientSocket = client;
        clientNo = clNo;
    }

    public void startConv()
    {
        int requestCount = 0; 
        byte[] byteFrom = new byte[10025];
        string XMLfromClient = null;
        string dataFromClient = null; 
        string serverResponse = null;
        string serverXMLResponse = null;
        NetworkStream serverStream = clientSocket.GetStream();

        requestCount = 0;
        while (true)
        {
            try
            {
                requestCount++;

                //Receive requerst from client
                serverStream.Read(byteFrom, 0, (int)clientSocket.ReceiveBufferSize);
                XMLfromClient = System.Text.Encoding.ASCII.GetString(byteFrom);
                callback2("\n >> From Client :" + clientNo + ". Message: \n" + XMLfromClient);


                //Console.WriteLine(">> From Client :" + clientNo + ". Message: \n" + XMLfromClient);

                //Send acknowledgement to client
                serverResponse = "Server to Client(" + clientNo + "). Request time: " + requestCount;  
                byte[] byteTo = Encoding.ASCII.GetBytes(serverResponse);
                serverStream.Write(byteTo, 0, byteTo.Length);

                serverStream.Flush();
                Console.WriteLine(">> " + serverResponse);
            }
            catch (Exception ex)
            {
                callback2(ex.ToString()); 
            }
        }
    }
}

And lastly is the code for client size: 最后是客户端大小的代码:

public partial class Form1 : Form
{
    System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
    NetworkStream serverStream;

    public Form1()
    {
        InitializeComponent();
    }

    public void msg(string mesg)
    {
        this.Display.Text += Environment.NewLine + " >> " + mesg;
    }

    private void SendButton_Click(object sender, EventArgs e)
    {
        serverStream = clientSocket.GetStream();
        byte[] outStream = System.Text.Encoding.ASCII.GetBytes("World Domination");
        serverStream.Write(outStream, 0, outStream.Length);
        serverStream.Flush();
        Thread receive = new Thread(new ThreadStart(ReceiveMess));

    }

    private void ReceiveMess()
    {
        serverStream = clientSocket.GetStream();
        byte[] inStream = new byte[10025];
        serverStream.Read(inStream, 0, (int)clientSocket.ReceiveBufferSize);
        string returndata = System.Text.Encoding.ASCII.GetString(inStream);
        msg("Data from Server : " + returndata);
    }
    private void connectButton_Click(object sender, EventArgs e)
    {
        msg("Client Started");
        clientSocket.Connect("127.0.0.1", 3000);
        this.Display.Text = "Client Socket Program - Server Connected ...";
    }
}

You seem to forget to start the receive thread: 您似乎忘记了启动receive线程:

private void SendButton_Click(object sender, EventArgs e)
{
    // ... skipped .........
    Thread receive = new Thread(new ThreadStart(ReceiveMess));
    receive.Start(); // <--- try adding this line
}

server will put to message to its interface then respond to the client 服务器将向其界面发送消息,然后响应客户端

So the server is a GUI app? 那么服务器是一个GUI应用程序吗?

Based on the code you appear to have blocking operations (eg. AcceptTcpClient ) on the GUI thread. 根据代码,您似乎在GUI线程上具有阻止操作(例如AcceptTcpClient )。 This is going to fail. 这将失败。 The GUI thread will block (and the UI will be unresponsive), which means updates to the IO from workers will block waiting on the UI (all UI operations must happen on the main thread). GUI线程将被阻止(并且UI将无响应),这意味着工作人员对IO的更新将阻止在UI上等待(所有UI操作必须在主线程上进行)。

Additionally spinning up a new thread for each connection is a bad idea. 另外,为每个连接分配一个新线程是一个坏主意。 Threads are expensive. 线程很昂贵。

You need to rewrite from the start (both client and server). 您需要从头开始重写(客户端和服务器)。

  • Avoid blocking operations (even file IO if you want maximum performance) on the GUI thread/ 避免在GUI线程/上阻塞操作(如果要获得最佳性能,甚至阻止文件IO)
  • All socket operations should be run in the thread pool (let the system manage the threads for you). 所有套接字操作都应在线程池中运行(让系统为您管理线程)。
  • Avoid waiting on the GUI from background threads (prefer BeginInvoke over Invoke ). 避免从后台线程在GUI上等待(最好使用BeginInvoke不是Invoke )。

Even better would be to use async : the system will manage the thread switching for you. 更好的方法是使用async :系统将为您管理线程切换。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM