简体   繁体   English

套接字仅接收消息C#的一部分

[英]Socket only receiving part of message C#

I have this bit of code that is receiving a series of messages: 我有这段代码正在接收一系列消息:

byte[] buffer = new byte[10240];
//...
sock.Receive(buffer);
string response = message(buffer);
Console.WriteLine("Message Recieved");
if (!verifyUser(response, sock))
Console.WriteLine("User Invalid");
//...
static private bool verifyUser(string userString, Socket sock)
{
   string[] userData = userString.Split(' ');
   int i = 0;
   while (true)
    {
        if (userData[0].ToUpper() != "USER")
        {
           byte[] buffer = message("WHO");
           sock.Send(buffer);
           userData = userString.Split(' ');
           i++;
           if (i > 4)
           {
                        return false;
                    }
                    continue;
                }
                else
                    break;
            }
Console.WriteLine("Connection recieved from " + userData[1] + " with hash of "/* + userData[2]*/);
}

The problem I'm having is that if I submit the username unkwntech all that gets displayed it unkwnt, and the second value never seems to get there. 我遇到的问题是,如果我提交用户名unkwntech,则所有显示的内容都将显示为unkwnt,而第二个值似乎永远都不会到达那里。 the app sending the data looks like this: 发送数据的应用程序如下所示:

static void Main(string[] args)
        {
            Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
            EndPoint remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 200);
            sock.Connect(remoteEP);
            byte[] buffer = Encoding.ASCII.GetBytes("USER unkwntech a3f5h4a35sfg");//Made up hash
            sock.Send(buffer);
            sock.Receive(buffer);
            Console.WriteLine(Encoding.ASCII.GetString(buffer));
            Console.ReadLine();
        }

You're assuming that when you send, all the data ends up in a single packet, and that you'll receive all the data in one go on the other end. 假设在发送时,所有数据最终都存储在一个数据包中,并且您将一次收到另一端的所有数据。 That's not how TCP/IP works. 这不是TCP / IP的工作方式。 It's a streaming protocol - you should never make assumptions about how much data you'll receive at a time. 这是一种流协议-绝对不要假设一次将收到多少数据。

Basically you need to read from the stream until either you've read all the data and the socket has been closed, or until you've got "enough" data. 基本上,您需要从流中读取数据,直到读取了所有数据并且套接字已关闭,或者直到您有“足够的”数据为止。 If you're in control of the protocol and it's a conversational protocol, it makes life a lot easier if each message you send is prefixed by its length - it means the other end knows how much data to expect. 如果您控制该协议,并且它是一种会话协议,那么,如果您发送的每条消息都以其长度作为前缀,则使生活变得更加轻松-这意味着另一端知道可以期待多少数据。

Check the return value of your Socket.Receive call. 检查Socket.Receive调用的返回值。 It returns the number of bytes received. 它返回接收的字节数。 You can put this call in a loop and read until you get the number of bytes you're expecting. 您可以将此调用置于循环中并读取,直到获得所需的字节数为止。 You should also guard against infinite looping by setting a max number of tries, or as John suggested, checking the status of the socket. 您还应该通过设置最大尝试次数来防止无限循环,或者按照John的建议,检查套接字的状态。 Also, don't assume a return value of zero means you've read the whole message. 另外,不要假设返回值为零就意味着您已经阅读了整个消息。

If your protocol has each message prefixed by its length, to be really bullet-proof your protocol should also define a marker byte to mark the end of the prefixed length header. 如果您的协议的每个消息都以其长度为前缀,则要真正防弹,您的协议还应定义一个标记字节来标记带前缀的长度标头的结尾。 Read one byte at a time until you see the marker byte. 一次读取一个字节,直到看到标记字节。 Then calculate the length of the message and read in larger chunks until you've read it all. 然后计算消息的长度,并阅读较大的块,直到全部阅读为止。

Socket.Receive defines an overload that lets you specify how many bytes you want to receive. Socket.Receive定义了一个重载,可让您指定要接收的字节数。 (However, you're not guaranteed to receive that many, so you still have to check the return value.) (但是,不能保证会收到那么多,所以您仍然必须检查返回值。)

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

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