向服务器发送多条消息? C#

发布于 2024-12-05 18:42:29 字数 2580 浏览 4 评论 0原文

我有一个快速而肮脏的问题。就目前情况而言,我有两个客户端和一个服务器正在运行。我可以毫无问题地从客户端向服务器传送消息。当我想从客户端读取两条消息而不是一条消息时,我的问题就出现了。

我收到的错误是:IOException 未处理。无法从传输连接读取数据:现有连接被远程主机强制关闭。

这是我在服务器端的代码:

private static void HandleClientComm(object client) { /** 创建一个包含 DatabaseFile 对象的列表 **/ 列出数据库 = new List();

        TcpClient tcpClient = (TcpClient)client;
        NetworkStream clientStream = tcpClient.GetStream();

        byte[] message = new byte[4096];
        int bytesRead;

        do
        {
            bytesRead = 0;

            try
            {
                // Blocks until a client sends a message                    
                bytesRead = clientStream.Read(message, 0, 4096);
            }
            catch (Exception)
            {
                // A socket error has occured
                break;
            }

            if (bytesRead == 0)
            {
                // The client has disconnected from the server
                break;
            }

            // Message has successfully been received
            ASCIIEncoding encoder = new ASCIIEncoding();

            Console.WriteLine("To: " + tcpClient.Client.LocalEndPoint);
            Console.WriteLine("From: " + tcpClient.Client.RemoteEndPoint);
            Console.WriteLine(encoder.GetString(message, 0, bytesRead));


            if (encoder.GetString(message, 0, bytesRead) == "OptionOneInsert")
            {
                byte[] message2 = new byte[4096];
                int bytesRead2 = 0;

                **bytesRead2 = clientStream.Read(message, 0, 4096);** //ERROR occurs here!

                Console.WriteLine("Attempting to go inside insert)");
                Menu.Insert(theDatabase, bytesRead2); 
            }

这是我的客户端代码:

        ASCIIEncoding encoder = new ASCIIEncoding();
        byte[] buffer = encoder.GetBytes("OptionOneInsert");

        Console.ReadLine(); 
        clientStream.Write(buffer, 0, buffer.Length);
        clientStream.Flush();

        NetworkStream clientStream2 = client.GetStream();
        String text = System.IO.File.ReadAllText("FirstNames.txt");
        clientStream2.Write(buffer, 0, buffer.Length);
        clientStream2.Flush();
        ASCIIEncoding encoder2 = new ASCIIEncoding();

        byte[] buffer2 = encoder2.GetBytes(text);
        Console.WriteLine("buffer is filled with content"); 
        Console.ReadLine();

当客户端发送消息“optionOne”时,服务器会很好地接收它。只有当我尝试发送名为“text”的字符串时,才会出现问题!

任何帮助将不胜感激 - 我不太熟悉套接字,因此我现在一直在努力尝试理解这一点

I have a quick and dirty question. So as it stands, i have two clients and a server running. I can communicate messages from the clients to the server without any problem. my problem appears when i want to read two messages from the client - rather than just one message.

The error which i receive is: IOException was unhandled. Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.

Here is my code on the server side:

private static void HandleClientComm(object client)
{
/** creating a list which contains DatabaseFile objects **/
List theDatabase = new List();

        TcpClient tcpClient = (TcpClient)client;
        NetworkStream clientStream = tcpClient.GetStream();

        byte[] message = new byte[4096];
        int bytesRead;

        do
        {
            bytesRead = 0;

            try
            {
                // Blocks until a client sends a message                    
                bytesRead = clientStream.Read(message, 0, 4096);
            }
            catch (Exception)
            {
                // A socket error has occured
                break;
            }

            if (bytesRead == 0)
            {
                // The client has disconnected from the server
                break;
            }

            // Message has successfully been received
            ASCIIEncoding encoder = new ASCIIEncoding();

            Console.WriteLine("To: " + tcpClient.Client.LocalEndPoint);
            Console.WriteLine("From: " + tcpClient.Client.RemoteEndPoint);
            Console.WriteLine(encoder.GetString(message, 0, bytesRead));


            if (encoder.GetString(message, 0, bytesRead) == "OptionOneInsert")
            {
                byte[] message2 = new byte[4096];
                int bytesRead2 = 0;

                **bytesRead2 = clientStream.Read(message, 0, 4096);** //ERROR occurs here!

                Console.WriteLine("Attempting to go inside insert)");
                Menu.Insert(theDatabase, bytesRead2); 
            }

Here is my client code:

        ASCIIEncoding encoder = new ASCIIEncoding();
        byte[] buffer = encoder.GetBytes("OptionOneInsert");

        Console.ReadLine(); 
        clientStream.Write(buffer, 0, buffer.Length);
        clientStream.Flush();

        NetworkStream clientStream2 = client.GetStream();
        String text = System.IO.File.ReadAllText("FirstNames.txt");
        clientStream2.Write(buffer, 0, buffer.Length);
        clientStream2.Flush();
        ASCIIEncoding encoder2 = new ASCIIEncoding();

        byte[] buffer2 = encoder2.GetBytes(text);
        Console.WriteLine("buffer is filled with content"); 
        Console.ReadLine();

When the client sends the message "optionOne" it is received by the server just fine. It's only when i attempt to send the string called "text" that the issues appears!

Any help would be greatly appreciated - I'm not all that familiar with Sockets, hence i've been struggling with trying to understand this for sometime now

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

谷夏 2024-12-12 18:42:29

这里有一个问题 - 没有任何内容可以指定一条消息的结束和另一条消息的开始。服务器很可能会一次性收到两条消息,或者先收到一半消息,然后再收到另一半。

避免这种情况的最简单方法是在每条消息中添加字节数作为前缀,例如采用固定的四字节格式。因此,要发送消息,您需要:

  • 将其从字符串编码为字节(最好使用 UTF-8 而不是 ASCII,除非您确定永远不需要任何非 ASCII 文本)
  • 写出字节数组的长度作为四字节值
  • 写出内容

在服务器上:

  • 读取四个字节(必要时循环 - 不能保证您甚至会一起读取这四个字节,尽管您几乎肯定会这样做)
  • 转换四个字节转换成一个整数
  • 分配一个字节数组该大小
  • 循环,从“当前位置”读取到缓冲区末尾,直到填满缓冲区
  • 将缓冲区转换为字符串

另一种选择是简单地使用 BinaryReaderBinaryWriter - ReadStringWriteString 使用长度前缀,诚然,形式略有不同。

您可以使用的另一种选择是使用分隔符(例如回车符),但这意味着如果您需要在要传输的文本中包含分隔符,则需要添加转义符。

You've got a big problem here - there's nothing to specify the end of one message and the start of another. It's quite possible that the server will receive two messages in one go, or half a message and then the other half.

The simplest way of avoiding that is to prefix each message with the number of bytes in it, e.g. as a fixed four-byte format. So to send a message you would:

  • Encoding it from a string to bytes (ideally using UTF-8 instead of ASCII unless you're sure you'll never need any non-ASCII text)
  • Write out the length of the byte array as a four-byte value
  • Write out the content

On the server:

  • Read four bytes (looping if necessary - there's no guarantee you'd even read those four bytes together, although you almost certainly will)
  • Convert the four bytes into an integer
  • Allocate a byte array of that size
  • Loop round, reading from "the current position" to the end of the buffer until you've filled the buffer
  • Convert the buffer into a string

Another alternative is simply to use BinaryReader and BinaryWriter - the ReadString and WriteString use length-prefixing, admittedly in a slightly different form.

Another alternative you could use is to have a delimiter (e.g. carriage-return) but that means you'll need to add escaping in if you ever need to include the delimiter in the text to transmit.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文