编辑:这个问题是从应用程序的角度来看的。如果在到达应用程序之前将1000个字节重新组装成单个缓冲区..那么我不关心它是否以某种方式被分段..
参见传输控制协议:
TCP提供了可靠有序的字节流从一个计算机上的程序到另一个计算机上的程序的传递。
"字节流"意味着接收方看到的没有消息边界。你可能会得到一个1000字节的消息或一千个1字节的消息,这取决于下面的内容以及你调用read/select的频率。
编辑:让我从应用程序的角度来澄清一下。不,TCP不能保证单次读取将给您发送者可能发送的所有1000字节(或1MB或1GB)数据包。因此,通常在TCP之上的协议包含具有总内容长度的固定长度的标头。例如,您可以始终发送一个字节,指示内容的总长度(以字节为单位),这将支持多达255个字节。
\0
,则以null结尾的字符串可以正常工作;各种“转义”的方法让您发送遵循此类限制的字节字符串。(已经存在针对此的协议,但没有真正广泛使用或广泛接受)。您可以决定消息包含多少字节。例如,在您的情况下,它是1000个字节。以下是可用的C#代码来实现相同的功能。该方法返回1000字节。中止代码为0字节;您可以根据需要进行调整。
使用方法:
strMsg = ReadData(thisTcpClient.Client, 1000, out bDisconnected);
步骤如下:
string ReadData(Socket sckClient, int nBytesToRead, out bool bShouldDisconnect)
{
bShouldDisconnect = false;
byte[] byteBuffer = new byte[nBytesToRead];
Array.Clear(byteBuffer, 0, byteBuffer.Length);
int nDataRead = 0;
int nStartIndex = 0;
while (nDataRead < nBytesToRead)
{
int nBytesRead = sckClient.Receive(byteBuffer, nStartIndex, nBytesToRead - nStartIndex, SocketFlags.None);
if (0 == nBytesRead)
{
bShouldDisconnect = true;
//0 bytes received; assuming disconnect signal
break;
}
nDataRead += nBytesRead;
nStartIndex += nBytesRead;
}
return Encoding.Default.GetString(byteBuffer, 0, nDataRead);
}
如果这篇文章没有帮到您,请告诉我们 (0: 祝您好运。
是的,有可能分批接收数据包。如果您正在使用Windows套接字,请参考MSDN文章和以下示例(摘自MSDN文章以供快速查看),希望对您有所帮助。
void CChatSocket::OnReceive(int nErrorCode)
{
CSocket::OnReceive(nErrorCode);
DWORD dwReceived;
if (IOCtl(FIONREAD, &dwReceived))
{
if (dwReceived >= dwExpected) // Process only if you have enough data
m_pDoc->ProcessPendingRead();
}
else
{
// Error handling here
}
}
TCP保证接收所有1000字节,但不一定按顺序(尽管对于接收应用程序来说似乎是这样),也不一定一次性接收完毕(除非您自己构造数据包并使其如此)。
话虽如此,对于像1000字节这样小的数据包,只要您在一次send
调用中发送,它很有可能会一次性发送完毕,但对于更大的传输可能不会。
recv()
函数需要参数来指定要返回多少数据,而不是告诉你数据包有多大的原因。在重传过程中,IP数据包可能会被分段。
因此,目标机器可能会接收到多个数据包 - 这些数据包将由TCP/IP堆栈重新组装。根据您使用的网络API,数据将以重新组装或原始数据包的形式提供给您。
这取决于已建立的MTU(最大传输单元)。如果您已建立的连接(一旦握手)参考了512字节的MTU,则需要两个或更多TCP数据包才能发送1000字节。