处理多个客户端的c#套接字

处理多个客户端的c#套接字,c#,sockets,tcp,C#,Sockets,Tcp,我有下面的代码,我想实现为我的服务器。据我所知,它是异步的。并且应该允许来自多个客户端的连接 public void Start() { TcpListener listener = new TcpListener(IPAddress.Any, 10250); listener.Start(); Console.WriteLine("Listening..."); while (true) { IAsyncResult

我有下面的代码,我想实现为我的服务器。据我所知,它是异步的。并且应该允许来自多个客户端的连接

public void Start()
{          
    TcpListener listener = new TcpListener(IPAddress.Any, 10250);
    listener.Start();
    Console.WriteLine("Listening...");

    while (true)
    {
        IAsyncResult res = listener.BeginAcceptTcpClient(HandleAsyncConnection, listener);
        connectionWaitHandle.WaitOne();
    }
}

private void HandleAsyncConnection(IAsyncResult res)
{
    TcpListener listener = (TcpListener)res.AsyncState;
    TcpClient client = listener.EndAcceptTcpClient(res);
    connectionWaitHandle.Set();

    StringBuilder sb = new StringBuilder();
    var data = new byte[client.ReceiveBufferSize];

    using (NetworkStream ns = client.GetStream())
    {             
        // Test reply
        Byte[] replyData = System.Text.Encoding.ASCII.GetBytes(DateTime.Now.ToString());
        ns.Write(replyData, 0, replyData.Length);
        ns.Flush();
        ns.Close();
    }

    client.Close();
}
我有一个测试应用程序,它只向我的服务器发出请求。正如您在代码中所看到的,服务器只回复其日期/时间。测试应用程序发送20个简单的测试字符串请求。对于每个请求,它都会打开一个套接字,将数据发送到我的服务器,然后再次关闭套接字


这在运行一个测试应用程序时效果很好。但是,如果我打开两个测试应用程序,第二个无法连接到服务器。我想是因为我在异步处理请求。因为我的测试应用程序在每次调用之前打开然后关闭套接字,所以我可以处理来自多个客户端的请求。

您这样做的方式,与使用
AcceptCpcClient
相比没有任何好处。只需循环并为每个接受的连接创建一个新线程:

public void Start()
{          
    TcpListener listener = new TcpListener(IPAddress.Any, 10250);
    listener.Start();
    Console.WriteLine("Listening...");
    while (canRun)
    {
       var client = listener.AcceptTcpClient();
       new Thread(ClientThread).Start(client);
    }
}

private void ClientThread(IAsyncResult res)
{
    TcpClient client = (TcpClient)res.AsyncState;

    StringBuilder sb = new StringBuilder();
    var data = new byte[client.ReceiveBufferSize];

    using (NetworkStream ns = client.GetStream())
    {             
        // Test reply
        Byte[] replyData = System.Text.Encoding.ASCII.GetBytes(DateTime.Now.ToString());
        ns.Write(replyData, 0, replyData.Length);
        ns.Flush();
        ns.Close();
    }

    client.Close();
}
使用异步方法时的一条黄金法则是阻止操作。阻塞会破坏使用异步操作的目的

public void Start()
{          
    TcpListener listener = new TcpListener(IPAddress.Any, 10250);
    listener.Start();
    Console.WriteLine("Listening...");
    listener.BeginAcceptTcpClient(OnAccept, listener);
}

private void OnAccept(IAsyncResult res)
{
    TcpListener listener = (TcpListener)res.AsyncState;
    TcpClient client = listener.EndAcceptTcpClient(res);

    StringBuilder sb = new StringBuilder();
    var data = new byte[client.ReceiveBufferSize];

    using (NetworkStream ns = client.GetStream())
    {             
        // Test reply
        Byte[] replyData = System.Text.Encoding.ASCII.GetBytes(DateTime.Now.ToString());
        ns.Write(replyData, 0, replyData.Length);
        ns.Flush();
        ns.Close();
    }

    client.Close();
}
编辑 如果使用>=.Net4.5,最好使用新的网络方法,然后允许采用
async
wait
。因此,最好以我在中提供的示例作为起点

原职 下面的代码演示了如何异步接受多个客户机,而不必为每个连接分离一个新线程

private TcpListener listener;
public void Start()
{          
    listener = new TcpListener(IPAddress.Any, 10250);
    listener.Start();
    Console.WriteLine("Listening...");
    StartAccept();

}
private void StartAccept()
{
    listener.BeginAcceptTcpClient(HandleAsyncConnection, listener);
}
private void HandleAsyncConnection(IAsyncResult res)
{
    StartAccept(); //listen for new connections again
    TcpClient client = listener.EndAcceptTcpClient(res);
    //proceed

}

您可以在大多数异步操作中使用此模式。

我有一些示例代码,完全符合您的要求,但它在我的笔记本电脑上。如果我记得的话,如果有人还没有给你回信,我今晚就发。很抱歉延迟。那太好了,谢谢。StartAccept()中是否需要有一个循环来保存应用程序。在连接到达之前一直处于活动状态?我假设这是一个控制台应用程序。我建议从应用程序的主方法调用Start,然后用Console.ReadKey或类似的方法阻止程序关闭。这似乎是迄今为止给我最好结果的代码。@spender我喜欢这段代码,因为它简单。但是在
//继续之后
可以使用代码示例帮助管理多个客户端。ie将消息唯一地发送给每个客户端。@Cesar是,否则服务器将只接受一个客户端。我建议不要在.Net 4.5中使用此类代码,并鼓励您采用允许您使用
async/await
的新网络方法。请看我的回答: