TCP | C#|接受多个客户端并在同一端口上管理它们

时间:2014-08-02 09:04:47

标签: c# multithreading tcp listener port

我尝试使用TCP在同一端口上接受和管理多个客户端。 我尝试使用我在谷歌上找到的一些答案,但没有一个有效。 主要思想是专用表单应用程序(用于客户端)连接到控制台应用程序(用作侦听器)。这就是我现在所拥有的:

static void Main(string[] args)
    {
        try
        {
            int counter = 0;

            // set the TcpListener on port 13000 
            int port = 13000;
            TcpListener server = new TcpListener(IPAddress.Any, port);

            // Start listening for client requests
            server.Start();


            // Buffer for reading data
            byte[] bytes = new byte[1024];
            string data;

            //Enter the listening loop 
            while (true)
            {
                Console.Write("Waiting for a connection... ");

                // Perform a blocking call to accept requests. 
                // You could also user server.AcceptSocket() here.
                TcpClient client = server.AcceptTcpClient();
                counter += 1;

                //Control each client
                var t = new Thread(new ParameterizedThreadStart(AccentClient));
                t.Start();

                //Handle the client that just connected
                handleClinet handle_client = new handleClinet();
                handle_client.startClient(client, counter.ToString());

                Console.WriteLine("Connected!");

                // Get a stream object for reading and writing
                NetworkStream stream = client.GetStream();

                int i;

                // Loop to receive all the data sent by the client.
                i = stream.Read(bytes, 0, bytes.Length);

                while (i != 0)
                {
                    // Translate data bytes to a ASCII string.
                    data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
                    Console.WriteLine(String.Format("Received: {0}", data));
                    Console.WriteLine("Fixed: {0}", data.Replace("$", ""));

                    // Process the data sent by the client.
                    data = data.Replace("$", "") + " Bla";

                    byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);

                    // Send back a response.
                    stream.Write(msg, 0, msg.Length);
                    Console.WriteLine(String.Format("Sent: {0}", data));
                    Console.WriteLine();

                    i = stream.Read(bytes, 0, bytes.Length);

                }

                // Shutdown and end connection
                //client.Close();
            }
        }
        catch (SocketException e)
        {
            Console.WriteLine("SocketException: {0}", e);
        }


        Console.WriteLine("Hit enter to continue...");
        Console.Read();
    }

    public static void AccentClient(object clientObj)
    {
        var client = clientObj as TcpClient;

    }
}

//Class to handle each client request separatly
public class handleClinet
{
    TcpClient clientSocket;
    string clNo;
    public void startClient(TcpClient inClientSocket, string clineNo)
    {
        this.clientSocket = inClientSocket;
        this.clNo = clineNo;
        Thread ctThread = new Thread(doChat);
        ctThread.Start();
    }
    private void doChat()
    {
        int requestCount = 0;
        byte[] bytesFrom = new byte[100000];
        string dataFromClient = null;
        Byte[] sendBytes = null;
        string serverResponse = null;
        string rCount = null;
        requestCount = 0;

        while ((true))
        {
            try
            {
                requestCount = requestCount + 1;
                NetworkStream networkStream = clientSocket.GetStream();
                networkStream.Read(bytesFrom, 0, clientSocket.ReceiveBufferSize);
                dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
                dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
                Console.WriteLine(" >> " + "From client- " + clNo + dataFromClient);

                rCount = Convert.ToString(requestCount);
                serverResponse = "Server to clinet(" + clNo + ") " + rCount;
                sendBytes = Encoding.ASCII.GetBytes(serverResponse);
                networkStream.Write(sendBytes, 0, sendBytes.Length);
                networkStream.Flush();
                Console.WriteLine(" >> " + serverResponse);
            }
            catch (Exception ex)
            {
                Console.WriteLine(" >> " + ex.ToString());
                break;
            }
        }
    }
}

由于

1 个答案:

答案 0 :(得分:0)

首先,您的AcceptClient方法不能完全执行任何操作:

public static void AccentClient(object clientObj)
{
    var client = clientObj as TcpClient;
}

因此,当客户端连接时,您正在产生的整个线程什么都不做。

其次,根据您当前的代码,当客户端连接时,您的主线程将停止侦听其他客户端并开始与刚刚连接的客户端进行通信:

            TcpClient client = server.AcceptTcpClient();

            // ...

            // Get a stream object for reading and writing
            NetworkStream stream = client.GetStream();
            int i = stream.Read(bytes, 0, bytes.Length);
            while (i != 0)
            {
                // ...
                i = stream.Read(bytes, 0, bytes.Length);
            }

因此,在当前的客户完成之前,不会接受任何其他客户。

第三,不仅你在主线程上接受客户端并与客户进行通信,而且你还在同一时间在另一个线程上与客户端进行通信:

            handleClinet handle_client = new handleClinet();
            handle_client.startClient(client, counter.ToString());

这些被定义为:

public void startClient(TcpClient inClientSocket, string clineNo)
{
    // ...
    Thread ctThread = new Thread(doChat);
    ctThread.Start();
}
private void doChat()
{
    // ...
    while ((true))
    {
            // ...
            requestCount = requestCount + 1;
            NetworkStream networkStream = clientSocket.GetStream();
            networkStream.Read(bytesFrom, 0, clientSocket.ReceiveBufferSize);
            dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
            dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
            Console.WriteLine(" >> " + "From client- " + clNo + dataFromClient);
            // ...
    }
}

这总是无法预测。


总结:

  1. 删除no-op。
  2. 更改代码,以便主线程仅调用异步客户端处理程序。
  3. 调用异步处理程序后,确保主线程中的循环不做任何其他操作,但立即返回接受下一个客户端。