c#客户端/服务器问题

本文关键字:问题 服务器 客户端 | 更新日期: 2023-09-27 18:09:37

我对这里发生的事情感到非常困惑。我一直在输入断点,但我就是不明白。基本上,我有一个客户端和一个服务器。我希望客户端发送数据的两个单独的字符串。通过放入断点,我注意到我的客户端实际上用适当的数据填充了两个字符串。但是,服务器永远不会看到第二个字符串。为什么会发生这种情况,我该如何解决?任何帮助都将非常感激!下面是我的代码:

服务器:

    private static void HandleClientComm(object client)
    {
        /** creating a list which contains DatabaseFile objects **/
        List<DatabaseFile> theDatabase = new List<DatabaseFile>();
        TcpClient tcpClient = (TcpClient)client;
        NetworkStream clientStream = tcpClient.GetStream();
        StringBuilder response = new StringBuilder();
        byte[] message = new byte[4096];
        int bytesRead;
        do
        {
            bytesRead = 0;
            try
            {
                /*do
                {
                    bytesRead = clientStream.Read(message, 0, message.Length);
                    response.Append(Encoding.ASCII.GetString(message, 0, bytesRead));
                } while (clientStream.DataAvailable);*/

当我改变这个注释代码bytesRead = clientStream。Read(message, 0,4096); i get a IOException Error,内容如下:cannot to write data to the transport connection:一个已存在的连接被远端主机强制关闭。因此,我将其更改为do while循环。我如何绕过这个IOException并接受第二个字符串?

                ASCIIEncoding encoder = new ASCIIEncoding();
                String file = encoder.GetString(message, 0, bytesRead);
                Menu.Insert(theDatabase, file); 
            }
            catch (Exception)
            {
                // A socket error has occured
                break;
            }
            if (bytesRead == 0)
            {
                // The client has disconnected from the server
                break;
            }
        } while (clientStream.DataAvailable);
        // Release connections
        clientStream.Close();
        tcpClient.Close();
    }

客户:

    static void Main(string[] args)
    {
        TcpClient client = new TcpClient();
        IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888);
        client.Connect(serverEndPoint);
        NetworkStream clientStream = client.GetStream();
        NetworkStream clientStream2 = client.GetStream();
        ASCIIEncoding encoder = new ASCIIEncoding();
        ASCIIEncoding encoder2 = new ASCIIEncoding();
        String text = System.IO.File.ReadAllText("FirstNames.txt");
        String text2 = System.IO.File.ReadAllText("LastNames.txt");
        byte[] buffer = encoder.GetBytes(text);
        Console.ReadLine(); 
        clientStream.Write(buffer, 0, buffer.Length);
        clientStream.Flush();
        Console.ReadLine();
        byte[] buffer2 = encoder2.GetBytes(text2);
        clientStream2.Write(buffer2, 0, buffer2.Length);
        clientStream2.Flush();
        Console.ReadLine(); 
    }
}

c#客户端/服务器问题

客户机和服务器之间的通信是这样进行的(注意步骤的顺序只是为了说明,运行时的实际顺序可能不同):

  1. 客户端:client.Connect(serverEndPoint)
    服务器:HandleClientComm(newClient)

  2. Client: clientStream.Write(buffer, 0, buffer.Length)
    服务器:bytesRead = clientStream.Read(message, 0, message.Length)
    注意,Read不能保证读取整个消息。只返回到目前为止已经接收到的部分是完全可以的

  3. Client: Console.ReadLine()
    Server: while (clientStream.DataAvailable)
    流上没有数据-客户端没有发送任何数据。即使没有ReadLine,这种情况也可能发生——在客户端再次发送数据之前有一个时间窗口

  4. Server: tcpClient.Close()

  5. 客户端:clientStream2.Write(buffer2, 0, buffer2.Length)
    你可以在这里得到一个异常,或者没有-取决于服务器是否已经关闭连接,在任何情况下,服务器不再读取

您需要定义您自己的消息协议,服务器和客户端都将遵守该协议。例如,您可以让客户端在完成发送时关闭连接:

客户:

using (var client = new TcpClient("localhost", 8888))
using (var clientStream = client.GetStream())
{
    var buffer = Encoding.ASCII.GetBytes( File.ReadAllText("FirstNames.txt") );
    clientStream.Write(buffer, 0, buffer.Length);
    buffer = Encoding.ASCII.GetBytes( File.ReadAllText("LastNames.txt") );
    clientStream.Write(buffer, 0, buffer.Length);
}

服务器:

using (var tcpClient = (TcpClient)client)
using (var clientStream = tcpClient.GetStream())
{
    // Store everything that the client sends.
    // This will work if the client closes the connection gracefully
    // after sending everything
    var receivedData = new MemoryStream();
    clientStream.CopyTo(receivedData);
    var rawBytes = receivedData.ToArray();
    var file = Encoding.ASCII.GetString(rawBytes, 0, rawBytes.Length);
    Menu.Insert(theDatabase, file);
}

协议很简单,可能对你的情况足够了。然而,它有一些问题应该在生产代码中解决(例如,如果客户端发送太多数据,耗尽服务器内存,如果客户端在没有关闭连接的情况下停止发送怎么办,等等)

因为while (clientStream.DataAvailable)在您的第一个客户端调用后不再为真。

退出服务器中的client-recv循环,只是因为DatAvailable为false。这意味着,如果客户端发送一帧数据(您正在使用)并暂停,那么您的服务器将在那一刻看到没有可用的数据并断开连接,即使在一瞬间之后来自客户端的另一帧数据即将进入。对话框的结束几乎总是基于所传递的数据的内容。当然,您永远不能指望DataAvailable恰好有一次为假。

接下来,如果你能提供更多关于使用的协议的信息,我们可以提供更多的帮助。例如,如果协议是两个字符串以CR/LF结尾发送,那么服务器循环应该检查缓冲区,以知道何时断开。