简体   繁体   English

使用TCP套接字发送数据时是否必须对大数据进行分块?

[英]Do I have to chunk large data while sending it with tcp socket?

I'm sending some not to large strings over tcp socket. 我通过TCP套接字发送一些不大字符串。 Today I send 2031 bytes and receiving end didn't get it all (I've send bigger messages - before 2040 bytes to days ago) - this isn't all that bad, program knew that something was wrong and send the data again (3rd try was successfull). 今天,我发送2031个字节,而接收端却一无所获(我已经发送了更大的消息-在2040个字节之前到几天前)-这还不是很糟糕,程序知道出了点问题,然后再次发送数据(第三次尝试成功)。 Now I'm wondering if I should split message into smaller chunks and send them in loop statement? 现在,我想知道是否应该将消息拆分为较小的块并在循环语句中发送它们? Is there something in my code that I'm missing? 我的代码中是否缺少某些内容?

Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sock.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket,SocketOptionName.ReceiveTimeout,0);
sock.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket,SocketOptionName.SendTimeout,0);           
LingerOption lingerOption = new LingerOption (true, 1); 
sock.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket,SocketOptionName.Linger, lingerOption );
sock.Blocking =  true;

try
{
    sock.Connect(_dostHostEp);
}
catch(SocketException e)                     
{                                       
    sock.Close();
    throw new Exception("Connection error (" + _dostHostEp.Address + ":" + _dostHostEp.Port + ")" + e.Message);             
}

try    
{
    sock.Send(Encoding.UTF8.GetBytes(message));                             
}
catch(SocketException e)
{                   
    sock.Close();               
    throw new Exception("Error while sending message to (" + _dostHostEp.Address + ":" + _dostHostEp.Port + ")" + e.Message);               
}

Why do you insist to get the 2031 bytes in one chunk? 为什么要坚持将2031字节分成一个块? Rather, you'd have to read the data at the receiver side until data exists. 相反,您必须在接收方读取数据, 直到数据存在。 This means that for example you read a chunk of 1800 bytes, another chunk of 231 bytes and then 0 bytes which means end of the data. 这意味着,例如,您读取了一个1800字节的块,另一个231字节的块,然后读取了0字节,这意味着数据结束。

I've always considered sending data without a well defined end character bad practice. 我一直考虑在没有明确定义结束字符的情况下发送数据是一种不好的做法。 I would personally recommend doing the following: 我个人建议执行以下操作:

As the sender, prepend the message with an STX-Character (0x02) and append the ETX-Character (0x03). 作为发件人,在邮件前添加STX字符(0x02),并附加ETX字符(0x03)。

The receiver should recognize STX as the start of a new message and then read (blocking?) until an ETX is received. 接收者应将STX识别为新消息的开始,然后读取(阻止?),直到接收到ETX。 If no ETX is received in reasonable time, there was a problem reading the entire message. 如果在合理的时间内未收到任何ETX,则说明读取整个消息时出现问题。

You don't need to use STX and ETX, you might also use \\r\\n or anything that is not part of your message itself. 您不需要使用STX和ETX,也可以使用\\ r \\ n或不属于消息本身的任何内容。

If you do not use a well defined end of message, the reader will never know when to stop reading and you will mess up your communication. 如果您没有使用定义良好的消息结尾,则读者将永远不知道何时停止阅读,并且会弄乱您的交流。

One sample case I've indentified as problematic: 我确定有问题的一个示例案例:

The sender sends two messages one after the other. 发送者一个接一个地发送两个消息。 Without an EndOfMessage-character, the receiver will try to read this as one single message. 如果没有EndOfMessage字符,则接收方将尝试将其作为一条消息读取。 With an EOM, the receiver can split the two messages and handle them both. 借助EOM,接收方可以拆分两个消息并同时处理它们。

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

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