TCP服务端能与客户端通信吗?

本文关键字:通信 客户端 服务 TCP | 更新日期: 2023-09-27 18:11:42

我有异步tcp服务器,可以接受多个客户端在同一时间。客户端从服务器请求数据的场景得到很好的服务。现在我试图实现的情况下,服务器必须找到一个特定的客户端,并发送一些数据给它,即客户端连接,但没有请求的数据,但服务器想要发送一些数据给它。如何找到已经在服务器和客户端之间运行的线程并将数据放置在其上?

服务器代码:

public async void RunServerAsync()
{
    tcpListener.Start();           
        while (true)
        {
            try
            { 
               var client = await tcpListener.AcceptTcpClientAsync();           
               Accept(client); 
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);                      
            }                  
         }                         
}
private async void Accept(TcpClient client)
{
   //get client information 
    String clientEndPoint = client.Client.RemoteEndPoint.ToString();            
    Console.WriteLine("Client connected at " + clientEndPoint );
    await Task.Yield ();
    try 
    {              
        using (client)
        using (NetworkStream stream = client.GetStream()) 
        {
            byte[] dataReceived = new byte[100];                  
            while (true) //read input stream                    
            {                    
                  try
                 {
                     int x = await stream.ReadAsync(dataReceived, 0, dataReceived.Length);
                     if (x != 0)
                     {                              
                         //pass on data for processing    
                         byte[] dataToSend = await ProcessData(dataReceived);
                         //send response,if any, to the client 
                         if (dataToSend != null)
                         {
                             await stream.WriteAsync(dataToSend, 0, dataToSend.Length);
                             ConsoleMessages.DisplayDataSent(dataReceived, dataToSend);
                         }
                     }
                 }
                 catch (ObjectDisposedException)
                 {
                     stream.Close();
                 }
            }                   
        }
    } //end try           
    catch (Exception ex) 
    {
        Console.WriteLine(ex.Message);
    }
}//end Accept(TcpClient client)

TCP服务端能与客户端通信吗?

你需要跟踪你的客户。例如:

ConcurrentDictionary<Guid, TcpClient> _clients = new ConcurrentDictionary<Guid, TcpClient>();
public async void RunServerAsync()
{
    tcpListener.Start();
    while (true)
    {
        try
        {
            var client = await tcpListener.AcceptTcpClientAsync();
            var clientId = Guid.NewGuid();
            Accept(clientId, client);
            _clients.TryAdd(clientId, client);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}
public Task SendAsync(Guid clientId, Byte[] buffer, Int32 offset, Int32 count)
{
    TcpClient client;
    if (_clients.TryGetValue(clientId, out client))
        return client.GetStream().WriteAsync(buffer, offset, count);
    // client disconnected, throw exception or just ignore
    return Task.FromResult<Object>(null);
}
public Boolean TryGetClient(Guid clientId, out TcpClient client)
{
    return _clients.TryGetValue(clientId, out client);
}
private async void Accept(Guid clientId, TcpClient client)
{
    //get client information 
    String clientEndPoint = client.Client.RemoteEndPoint.ToString();
    Console.WriteLine("Client connected at " + clientEndPoint);
    await Task.Yield();
    try
    {
        using (client)
        using (NetworkStream stream = client.GetStream())
        {
            byte[] dataReceived = new byte[100];
            while (true) //read input stream                    
            {
                try
                {
                    int x = await stream.ReadAsync(dataReceived, 0, dataReceived.Length);
                    if (x != 0)
                    {
                        //pass on data for processing    
                        byte[] dataToSend = await ProcessData(dataReceived);
                        //send response,if any, to the client 
                        if (dataToSend != null)
                        {
                            await stream.WriteAsync(dataToSend, 0, dataToSend.Length);
                            ConsoleMessages.DisplayDataSent(dataReceived, dataToSend);
                        }
                    }
                }
                catch (ObjectDisposedException)
                {
                    stream.Close();
                }
            }
        }
    } //end try           
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
    finally
    {
        // deregister client
        _clients.TryRemove(clientId, out client);
    }
}//end Accept(TcpClient client)

TCP是双向的,所以任何一方都可以随时发送数据。

您需要做的是在Accept上存储对TcpClient的引用,如:

//Class Level
List<TcpClient> connectedClients = List<TcpClient>();
private async void Accept(TcpClient client)
{
    connectedClients.Add(client);
    ...
}
public SendMessage(int index, String message)
{
   //pseudo-code
   connectedClients[index].Send(message);
}

通常我会在连接时引发一个事件,因此使用该类的任何人都可以获得新客户端的索引。发送消息代码是伪代码,在MSDN上有很好的例子说明如何实际执行发送。