简体   繁体   English

接收消息并通过 NetworkStream 向客户端发送消息

[英]Receiving messages and sending messages over NetworkStream to a Client

I have a question about sending and receiving messages from a TCPListener server to a client over a Network Stream in C#.我有一个关于通过 C# 中的网络流从 TCPListener 服务器向客户端发送和接收消息的问题。 Right now, my TCPListener instance can receive one message from a client and write it to the server console, and it can accept one input string and send it back to the client.现在,我的 TCPListener 实例可以从客户端接收一条消息并将其写入服务器控制台,它可以接受一个输入字符串并将其发送回客户端。 But I wish to improve the function to accept multiple consecutive messages from a client and send multiple consecutive responses back to the client.但我希望改进功能以接受来自客户端的多个连续消息并将多个连续响应发送回客户端。 Does anyone happen to have any pointers if the ReadAsync and WriteAsync functions of a NetworkStream can handle receiving multiple consecutive messages or sending multiple consecutive messages and if there is a better method to achieve this?如果 NetworkStream 的 ReadAsync 和 WriteAsync 函数可以处理接收多个连续消息或发送多个连续消息,并且是否有更好的方法来实现这一点,是否有人碰巧有任何指针? Also, since the Console.ReadLine function will block in the case the server never receives any user input from ReadLine (and no Enter key is pushed), is there a way to test if there's optional user input from the keyboard?此外,由于 Console.ReadLine 函数将在服务器从未从 ReadLine 接收任何用户输入(并且没有按下 Enter 键)的情况下阻塞,有没有办法测试是否有来自键盘的可选用户输入? That way I could try to execute the send message commands only if the server received some kind of console input from the user, and could continue receiving client messages otherwise.这样我才可以尝试仅在服务器收到来自用户的某种控制台输入时执行发送消息命令,否则可以继续接收客户端消息。

   public static async Task getMessage(TcpListener server)
      {
            byte[] bytes = new byte[256];
            using (var theStream = await server.AcceptTcpClientAsync())
            {
                using (var tcpStream = theStream.GetStream())
                {

                    await tcpStream.ReadAsync(bytes, 0, bytes.Length);
                    var msg = Encoding.UTF8.GetString(bytes);
                    Console.WriteLine(msg);
                    var payload = Console.ReadLine();
                    var bytes2 = Encoding.UTF8.GetBytes(payload);
                    await tcpStream.WriteAsync(bytes2, 0, bytes2.Length);
                }

           }

      } 

It is interesting to see a server implementation dedicated to only one client!看到一个服务器实现只专用于一个客户端,这很有趣!

TCP is a two-way communication protocol so yes, you can, of course, send what you want and when you want and receive anything at the same time. TCP 是一种双向通信协议,所以是的,您当然可以在需要时发送您想要的内容并同时接收任何内容。

I tried to put comments in the source to let it explain itself.我试图在源代码中添加注释,让它自行解释。

But the critical point is declaring the TcpClient and NetworkStream instances as static variables so that the main thread (the thread which reads from the console and sends the payload to the client) can access them但关键点是将TcpClientNetworkStream实例声明为静态变量,以便主线程(从控制台读取并将有效负载发送到客户端的线程)可以访问它们

Hope this helps.希望这可以帮助。

public static async Task getMessage(TcpListener server)
{
    byte[] bytes = new byte[256];
    using (theStream = await server.AcceptTcpClientAsync())
    {
        using (tcpStream = theStream.GetStream())
        {
            // We are using an infinite loop which ends when zero bytes have been received.
            // Receiving zero bytes means the transmission is over (client disconnected)
            while (await tcpStream.ReadAsync(bytes, 0, bytes.Length) > 0)
            {
                var msg = Encoding.UTF8.GetString(bytes);
                Console.WriteLine(msg);
            }
            Console.WriteLine("Client has disconnected");
        }
    }
}

/// <summary>
/// Transmists the payload to the client
/// </summary>
/// <param name="payload">The payload to transmit to the client</param>
/// <returns></returns>
static async Task Transmit(string payload)
{
    var bytes2 = Encoding.UTF8.GetBytes(payload);
    await tcpStream.WriteAsync(bytes2, 0, bytes2.Length);
}

// We are declaring the TcpClient and NetworkStream as static variables
// to be able to access them from all the threads.
private static TcpClient theStream;
public static NetworkStream tcpStream;

static void Main(string[] args)
{
    TcpListener server = new TcpListener(IPAddress.Loopback, 9876);
    server.Start();

    // Start the task getMessage() to accept a client and receive
    Task.Run(() => getMessage(server));

    string payload;
    while ((payload = Console.ReadLine()) != "exit")
    {
        // Check if the client has connected.
        if (tcpStream != null)
        {
            // Check if they are still connected
            if (theStream.Client.Connected)
            {
                Task.Run(() => Transmit(payload));
            }
            else
            {
                Console.WriteLine("the client connection is lost");
                break;
            }
        }
        else
        {
            Console.WriteLine("The client has not connected yet.");
        }
    }

    Console.WriteLine("Stopping the server");
    server.Stop();
}

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

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