【问题标题】:Working on client server using sockets and tcp\ip in C#在 C# 中使用套接字和 tcp\ip 在客户端服务器上工作
【发布时间】:2020-05-20 03:19:00
【问题描述】:

我正在处理客户端-服务器数据接收。我能够从我的仪表服务器接收数据。代码如下

listner = new TcpListener(new IPEndPoint(IPAddress.Any, port));
        Console.WriteLine("Listening...");
        listner.Start();
        while (true)
        {
            try
            {
                //---incoming client connected---
                TcpClient client = listner.AcceptTcpClient();

                //---get the incoming data through a network stream---
                NetworkStream nwStream = client.GetStream();
                byte[] buffer = new byte[client.ReceiveBufferSize];

                //---read incoming stream---
                int bytesRead = nwStream.Read(buffer, 0, client.ReceiveBufferSize);

                //---convert the data received into a string---
                string dataReceived = BitConverter.ToString(buffer, 0, bytesRead);
                //Encoding.ASCII.GetString(buffer, 0, bytesRead);
                //Console.WriteLine("Received : " + dataReceived);
                //MessageBox.Show("Data Received", dataReceived);
                //---write back the text to the client---
                //Console.WriteLine("Sending back : " + dataReceived);
                //nwStream.Write(buffer, 0, bytesRead);
                client.Close();
            }
            catch (Exception ex)
            {

            }

使用上面的代码,我可以接收数据。但我想执行以下操作

  1. 继续监听端口
  2. 在收听时我想向服务器(仪表)发送一些字节
  3. 发送一些数据后从服务器获取响应。

我知道有很多客户端-服务器教程,但它们有单独的服务器和客户端实现。我只想处理客户端(我的软件)。我也试过Asynchronous Server Socket Example

任何帮助将不胜感激。

【问题讨论】:

    标签: c# tcp client-server ip-address


    【解决方案1】:

    您的服务器需要不断地监听来自客户端的连接。每次它获得连接时,您都会从操作系统获得一个新的TcpClient 来处理该连接。您从操作系统获得的 TcpClient 有时称为 Child TcpClient,因为它是由侦听端口创建的。但它在功能上与任何其他套接字相同。

    这很容易通过 async/await 模式实现。

    首先,您需要一个等待连接的侦听器,每次它获得连接时,它都会将此传递给另一个处理子 TcpClient 的任务。例如,

    static async Task StartTcpServerAsync()
    {
        var tcpListener = new TcpListener(new IPEndPoint(IPAddress.Any, 9999));
        tcpListener.Start();
    
        while (true)
        {
            var tcpClient = await tcpListener.AcceptTcpClientAsync();
    
            // Fire and forget the Child connection
            _ = StartChildTcpClientAsync(tcpClient);
        }
    }
    

    在上面的样板代码中,我们完全忘记了 ChildTcpClient 任务。你可能想要也可能不想要这个。如果您使任务完全自给自足(就像这个演示一样),那么主要任务可能永远不需要知道它是否完成。但是,如果您需要能够在 ChildTcpClient 任务和主任务之间提供反馈,那么您需要提供一些额外的代码来管理它,并且您首先将从 StartChildTcpClientAsync(tcpClient); 返回的任务存储在某处以便您可以观察它。您可以在此处使用Task.Run(),但在控制台应用程序中不是必需的。

    现在你已经有了你的监听任务,你需要一个 ChildTcpClient 任务,例如:

    static async Task StartChildTcpClientAsync(TcpClient tcpClient)
    {
        Console.WriteLine($"Connection received from: {tcpClient.Client.RemoteEndPoint.ToString()}");
    
        using var stream = tcpClient.GetStream();
        var buffer = new byte[1024];
        while (true)
        {
            var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
            await stream.WriteAsync(buffer, 0, bytesRead);
        }
    }
    

    这是一个超级简单的 Tcp echo 客户端。它没有流量控制,也没有错误处理,即使在客户端断开连接后,任务也会永远坐在那里等待客户端发送一些数据。此任务只是“等待”无穷大(或直到发生异常),因此您需要在此处添加一些代码来管理客户端,检查客户端是否仍处于连接状态,等等

    要将它们组合在一起,您只需要这样的 main:

    static async Task Main(string[] args)
    {
        await StartTcpServerAsync();
        // Will never exit unless tcpListener.AcceptTcpClientAsync();
        // throws an exception
    }
    

    就是这样,您有一个控制台应用程序,它等待无限数量的客户端连接,并且每次连接时它都有自己的任务来处理 IO。

    【讨论】:

    • 是的。仅受 CPU 和内存限制。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多