在TCP中接收数据

时间:2009-10-26 05:16:04

标签: c# c++ networking tcp

如果我在TCP中发送1000个字节,它是否保证接收器将获得整个1000字节“togther”?或者他首先只能获得500个字节,之后他会收到其他字节?

编辑:问题来自应用程序的观点。如果1000字节在到达应用程序之前重新组装成单个缓冲区..那么我不在乎它是否在路上被分割..

10 个答案:

答案 0 :(得分:13)

请参阅Transmission Control Protocol

  

TCP提供从一台计算机上的程序到另一台计算机上另一程序的可靠,有序的字节流传送。

“流”意味着从接收者的角度来看没有消息边界。您可以获得一条1000字节的消息或一千条1字节的消息,具体取决于下面的内容以及调用read / select的频率。

编辑:让我从应用程序的角度澄清一下。不,TCP不保证单次读取会为您提供发送方可能发送的所有1000字节(或1MB或1GB)数据包。因此,TCP上方的协议通常包含固定长度的头部,其中包含总内容长度。例如,您总是可以发送1个字节,表示内容的总长度(以字节为单位),最多可支持255个字节。

答案 1 :(得分:3)

正如其他答案所示,TCP是协议 - 发送的每个字节都将被接收(一次并以相同的顺序),但没有内在的“消息边界” - 是否所有字节在一次.send次呼叫中发送,或多次发送,可能仍会在一次或多次.receive次呼叫中接收。

因此,如果您需要“消息边界”,则需要将它们置于TCP流的顶层,IOW,基本上是在应用程序级别。例如,如果您知道您发送的字节将永远不会包含\0,则以null结尾的字符串可以正常工作;各种“转义”方法让你发送不遵守这些限制的字节串。 (现有协议,但没有一个真正普遍或广泛接受)。

答案 2 :(得分:2)

基本上就TCP来说,它只保证从一端发送到另一端的数据将以相同的顺序发送。 现在通常你要做的就是有一个内部缓冲区,它一直保持循环,直到它收到你的1000字节“数据包”。 因为上面提到的recv命令返回实际收到的数量。 因此,通常您必须在TCP之上实现协议,以确保以适当的速度发送数据。因为如果你发送()一次运行中的所有数据,它将使位于下层的网络堆栈重载,这将导致复杂化。 因此,通常在协议中会发送一个微小的确认数据包,以确认发送了1000个字节的数据包。

答案 3 :(得分:2)

您在邮件中决定邮件应包含多少字节。例如在你的情况下它是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:祝你好运。

答案 4 :(得分:1)

是的,有机会逐个接收数据包。希望这个msdn article和以下示例(从msdn中的article获取以便快速查看)对您有所帮助,如果您使用的是Windows套接字。

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
   }
}

答案 5 :(得分:0)

TCP保证它们将接收所有1000个字节,但不一定按顺序(但是,它将对接收应用程序显示)并且不一定全部(除非您自己制作数据包并且这样做。)。

也就是说,对于一个小到1000字节的数据包,只要你在send的一次调用中发送一个数据包就很有可能,但是对于较大的传输,它可能不会

答案 6 :(得分:0)

TCP层唯一保证的是接收器将接收:

  • 发件人传输的所有字节
  • 以相同的顺序

根本不保证字节如何被分成“数据包”。您可能阅读的有关MTU,数据包碎片,最大段大小或其他任何内容的所有内容都在TCP套接字层之下,并且无关紧要。 TCP仅提供流服务

参考您的问题,这意味着接收器可能会收到前500个字节,然后接收下500个字节。或者,接收器可能一次接收一个字节的数据,如果这是它要求的。这就是recv()函数采用一个参数来告诉它返回的数据的原因,而不是告诉你数据包有多大。< / p>

答案 7 :(得分:-1)

传输控制协议通过要求确认接收方向发送方成功传送每个分组来保证所有分组的成功传送。通过这个定义,当有效载荷的大小超过MTU (maximum transmission unit)时,接收器将始终以块的形式接收有效载荷。

有关详细信息,请参阅Transmission Control Protocol

答案 8 :(得分:-1)

在重新传输期间,IP数据包可能会碎片化。

因此目标计算机可能会收到多个数据包 - 这些数据包将由TCP / IP堆栈重新组装。根据您使用的网络API,数据将提供给重组或RAW数据包。

答案 9 :(得分:-1)

取决于建立的MTU(最大传输单位)。如果您的建立连接(一旦握手)指的是512字节的MTU,您将需要两个或更多TCP数据包来发送1000个字节。