TCP不可靠吗?

TCP不可靠吗?,c,sockets,tcp,C,Sockets,Tcp,我相信TCP是可靠的。如果write(socket,buf,buf_len)和close(socket)返回无误,则接收器将接收长度为buf_len的完全相同的buf数据 但是说TCP是不可靠的 A: B: int sock = socket(AF_INET, SOCK_STREAM, 0); bind(sock, &local, sizeof(local)); listen(sock, 128); int client=accept(sock, &local, locallen

我相信TCP是可靠的。如果
write(socket,buf,buf_len)
close(socket)
返回无误,则接收器将接收长度为
buf_len
的完全相同的
buf
数据

但是说TCP是不可靠的

A:

B:

int sock = socket(AF_INET, SOCK_STREAM, 0);
bind(sock, &local, sizeof(local));
listen(sock, 128);
int client=accept(sock, &local, locallen);
write(client, "220 Welcome\r\n", 13);

int bytesRead=0, res;
for(;;) {
    res = read(client, buffer, 4096);
    if(res < 0)  {
        perror("read");
        exit(1);
    }
    if(!res)
        break;
    bytesRead += res;
}
printf("%d\n", bytesRead);
不幸的是,正确的答案是D。但这怎么会发生呢?程序A 报告所有数据已正确发送

如果这篇文章是真的,我必须改变主意。但我不确定这篇文章是否属实


这篇文章是真的吗

TCP/IP提供了可靠性,这意味着它允许重新传输丢失的数据包,从而确保(最终)接收到所有传输的数据,或者您会收到超时错误。要么你的东西被送到了,要么你被告知超时错误

顺便说一句,TCP/IP在某种程度上是可靠的,它保证了网络正常工作时的传输。。。如果拔掉电缆,TCP/IP将无法传送数据包

请注意,您至少应将指针置于
缓冲区内
缓冲区内

void ReadXBytes(int socket, unsigned int x, void* buffer)
{
    int bytesRead = 0;
    int result;
    while (bytesRead < x)
    {
        result = read(socket, buffer + bytesRead, x - bytesRead);
        if (result < 1 )
        {
            // Throw your error.
        }

        bytesRead += result;
    }
}
void ReadXBytes(整数套接字、无符号整数x、void*缓冲区)
{
int字节读取=0;
int结果;
while(字节读取
TCP是可靠的(至少当较低级别的协议是可靠的时),但是程序员可能以不可靠的方式使用它

这里的问题是,在另一端正确接收到所有发送的数据之前,不应关闭套接字:关闭信号可能会在最后一个数据仍在传输之前破坏连接

确保同伴正确接收的正确方法是

程序A报告所有数据都已正确发送

否。在程序A中返回
write
仅意味着返回的字节数已传递到操作系统的内核。它并不声称数据已由本地系统发送,已由远程系统接收,甚至已由远程应用程序处理

我相信TCP是可靠的

TCP仅在传输层提供可靠性。这仅意味着它将确保检测到数据丢失(并重新传输数据包)、检测到数据重复(并丢弃重复数据)以及检测到并修复数据包重新排序


TCP不要求更高层次的可靠性。如果应用程序需要,则必须由应用程序本身提供

TCP/IP是可靠的,因为“可靠”一词的含义非常特殊(且有限)

具体地说,当write()返回1000000时,它向您做出以下承诺:

  • 1000000字节的数据已复制到TCP套接字的传出数据缓冲区中,从现在起,TCP/IP堆栈负责将这些字节传送到远程程序
  • 如果这些字节能够被交付(付出合理的努力),那么它们将被交付,即使一些传输的TCP数据包在交付过程中被丢弃
  • 如果字节确实被传递,它们将被准确有序地传递(相对于彼此,也相对于传递给同一套接字上先前和后续write()调用的数据)
  • 但也有一些write()不能(通常也不能)提供的保证。特别是:

  • write()不能保证接收应用程序在调用recv()获取所有1000000字节之前不会退出或崩溃
  • write()不能保证接收应用程序将正确处理它确实接收到的字节(即,它可能只是忽略它们或错误处理它们,而不是对它们执行操作)
  • write()不能保证接收应用程序会将recv()调用到recv()这些字节(也就是说,它可能只是保持套接字打开,但永远不会对其调用recv()
  • write()无法保证您的计算机和远程计算机之间的网络基础结构能够传输字节,即如果某些数据包丢失,TCP层将重新发送,但如果有人将电缆从电缆调制解调器中拔出,然后,字节根本无法到达其目的地,在尝试几分钟并未能获得ACK后,TCP层将放弃并错误地断开连接
  • write()不能保证接收应用程序100%正确地处理套接字关闭问题(如果不正确,则在远程程序关闭套接字之前发送的任何数据都可能被静默删除,因为没有接收器可以接收)
  • write()不保证接收应用程序将以与发送字节相同的段大小接收字节。i、 e.仅仅因为您在对send()的一次调用中发送了1000000字节,并不意味着接收应用程序可以在对recv()的一次调用中接收1000000字节。他可能会以任意大小的块接收数据,例如,每recv()调用1字节,或每recv调用1000字节,或TCP层希望提供的任何其他大小
  • 请注意,在上面列出的所有情况下,问题都是在write()返回后发生的,这就是为什么write()不能在发生这些情况时仅返回错误代码的原因。(当然,稍后对write()的调用可能会返回错误代码,但这并不能特别帮助您知道已传递字节和未传递字节之间的行的位置)

    TLDR:TCP/IP比UDP更可靠,但不能100%保证不会出错。如果你真的想确保你的字节在接收端得到了处理,你需要进行编程
    A) 1000000 
    B) something less than 1000000 
    C) it will exit reporting an error 
    D) could be any of the above
    
    void ReadXBytes(int socket, unsigned int x, void* buffer)
    {
        int bytesRead = 0;
        int result;
        while (bytesRead < x)
        {
            result = read(socket, buffer + bytesRead, x - bytesRead);
            if (result < 1 )
            {
                // Throw your error.
            }
    
            bytesRead += result;
        }
    }