TCP接收数据

发布于 2024-08-09 02:20:16 字数 174 浏览 5 评论 0原文

如果我在 TCP 中发送 1000 字节,是否能保证接收者“一起”收到全部 1000 字节?或者也许他首先只会收到 500 个字节,然后他会收到其他字节?

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

If i send 1000 bytes in TCP, does it guarantee that the receiver will get the entire 1000 bytes "togther"? or perhaps he will first only get 500 bytes, and later he'll receive the other bytes?

EDIT: the question comes from the application's point of view. If the 1000 bytes are reassembles into a single buffer before they reach the application .. then i don't care if it was fragmented in the way..

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

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

发布评论

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

评论(10

街道布景 2024-08-16 02:20:17

IP 数据包在重传期间可能会出现碎片。

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

The IP packets may get fragmented during retransmission.

So the destination machine may receive multiple packets - which will be reassembled back by TCP/IP stack. Depending on the network API you are using - the data will be given to you either reassembled or in RAW packets.

笑忘罢 2024-08-16 02:20:17

这取决于建立的MTU(最大传输单元)。如果您建立的连接(握手后)涉及 512 字节的 MTU,则您将需要两个或更多 TCP 数据包来发送 1000 字节。

It depends of the stablished MTU (Maximum transfer unit). If your stablished connection (once handshaked) refers to a MTU of 512 bytes you will need two or more TCP packets to send 1000 bytes.

拥抱没勇气 2024-08-16 02:20:17

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

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

As other answers indicated, TCP is a stream protocol -- every byte sent will be received (once and in the same order), but there are no intrinsic "message boundaries" -- whether all bytes are sent in a single .send call, or multiple ones, they might still be received in one or multiple .receive calls.

So, if you need "message boundaries", you need to impose them on top of the TCP stream, IOW, essentially, at application level. For example, if you know the bytes you're sending will never contain a \0, null-terminated strings work fine; various methods of "escaping" let you send strings of bytes which obey no such limitations. (There are existing protocols for this but none is really widespread or widely accepted).

末骤雨初歇 2024-08-16 02:20:17

基本上就 TCP 而言,它仅保证从一端发送到另一端的数据将以相同的顺序发送。
现在,通常您需要做的是拥有一个内部缓冲区,该缓冲区不断循环,直到收到 1000 字节的“数据包”。
因为前面提到的recv命令会返回实际接收到的数据量。
因此,通常您必须在 TCP 之上实现一个协议,以确保以适当的速度发送数据。因为如果您在一次运行中 send() 所有数据,则会导致底层网络堆栈过载,从而导致复杂性。
所以协议中通常会发回一个微小的确认包来确认1000字节的数据包已发送。

Basically as far as TCP goes it only guarantees that the data sent from one end to the other end will be sent in the same order.
Now usually what you'll have to do is have an internal buffer that keeps looping until it has received your 1000 byte "packet".
Because the recv command as mentioned returns how much has actually been received.
So usually you'll have to then implement a protocol on top of TCP to make sure you send data at an appropriate speed. Because if you send() all the data in one run through it will overload the under lying networking stack, and which will cause complications.
So usually in the protocol there is a tiny acknowledgement packet sent back to confirm that the packet of 1000 bytes are sent.

听闻余生 2024-08-16 02:20:17

您在消息中决定消息应包含多少字节。例如,在您的例子中,它是 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:祝你好运。

You decide, in your message that how many bytes your message shall contain. For instance in your case its 1000. Following is up and running C# code to achieve the same. The method returns with 1000 bytes. The abort code is 0 bytes; you can tailor that according to your needs.

Usage:

strMsg = ReadData(thisTcpClient.Client, 1000, out bDisconnected);

Following is the method:

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

Let us know this didn't help you (0: Good luck.

阪姬 2024-08-16 02:20:17

是的,有机会逐部分接收数据包。希望这篇 msdn 文章 和以下示例(取自来自 msdn 中的文章以供快速查看)如果您使用 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
   }
}

Yes, there is a chance for receiving packets part by part. Hope this msdn article and following example (taken from the article in msdn for quick review) would be helpful to you if you are using windows sockets.

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
   }
}
夜光 2024-08-16 02:20:17

TCP 保证它们将接收所有 1000 个字节,但不一定按顺序(尽管对接收应用程序来说似乎是这样),也不一定一次性全部接收(除非您自己制作数据包并使其如此。)。

也就是说,对于小至 1000 字节的数据包,只要您在一次调用 send 中执行此操作,它很有可能会在一个数据包中发送,但对于较大的传输,可能不会。

TCP guarantees that they will recieve all 1000 bytes, but not necessarily in order (though, it will appear so to the recieving application) and not necessarily all at once (unless you craft the packet yourself and make it so.).

That said, for a packet as small as 1000 bytes, there is a good chance it'll send in one packet as long as you do it in one call to send, though for larger transmissions it may not.

相守太难 2024-08-16 02:20:17

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

  • 传输的所有字节
  • 发送方以相同顺序

对于如何将字节分割成“数据包”根本没有任何保证。您可能读到的所有有关 MTU、数据包分段、最大段大小或其他内容的内容都位于 TCP 套接字层之下,并且是无关紧要的。 TCP提供流服务。

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

The only thing that the TCP layer guarantees is that the receiver will receive:

  • all the bytes transmitted by the sender
  • in the same order

There are no guarantees at all about how the bytes might be split up into "packets". All the stuff you might read about MTU, packet fragmentation, maximum segment size, or whatever else is all below the layer of TCP sockets, and is irrelevant. TCP provides a stream service only.

With reference to your question, this means that the receiver may receive the first 500 bytes, then the next 500 bytes later. Or, the receiver might receive the data one byte at a time, if that's what it asks for. This is the reason that the recv() function takes a parameter that tells it how much data to return, instead of it telling you how big a packet is.

帅哥哥的热头脑 2024-08-16 02:20:17

传输控制协议通过要求接收方确认每个数据包已成功交付给发送方来保证所有数据包的成功交付。根据此定义,当有效负载的大小超过 时,接收方将始终以块的形式接收有效负载MTU(最大传输单元)

有关详细信息,请阅读传输控制协议

The transmission control protocol guarantees successful delivery of all packets by requiring acknowledgment of the successful delivery of each packet to the sender by the receiver. By this definition the receiver will always receive the payload in chunks when the size of the payload exceeds the MTU (maximum transmission unit).

For more information please read Transmission Control Protocol.

我一直都在从未离去 2024-08-16 02:20:16

请参阅传输控制协议

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

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

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

See Transmission Control Protocol:

TCP provides reliable, ordered delivery of a stream of bytes from a program on one computer to another program on another computer.

A "stream" means that there is no message boundary from the receiver's point of view. You could get one 1000 byte message or one thousand 1 byte messages depending on what's underneath and how often you call read/select.

Edit: Let me clarify from the application's point of view. No, TCP will not guarantee that the single read would give you all of the 1000 bytes (or 1MB or 1GB) packet the sender may have sent. Thus, a protocol above the TCP usually contains fixed length header with the total content length in it. For example you could always send 1 byte that indicates the total length of the content in bytes, which would support up to 255 bytes.

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