我相信TCP是可靠的。如果write(socket, buf, buf_len)
和close(socket)
没有错误地返回,则接收方将收到buf
长度为buf_len
的完全相同的数据。
但是this article说TCP不可靠。
A:
sock = socket(AF_INET, SOCK_STREAM, 0); connect(sock, &remote, sizeof(remote)); write(sock, buffer, 1000000); // returns 1000000 close(sock);
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);
测验问题 - 完成后B程序会打印什么?
A) 1000000 B) something less than 1000000 C) it will exit reporting an error D) could be any of the above
遗憾的是,正确的答案是“D”。但这怎么可能发生呢?计划A. 报告说所有数据都已正确发送!
如果这篇文章属实,我必须改变主意。但我不确定这篇文章是否属实。
这篇文章是真的吗?
答案 0 :(得分:4)
TCP 可靠(至少在较低级协议时),但程序员可能以不可靠的方式使用它。
这里的问题是在另一方没有正确接收到所有发送的数据之前不应该关闭套接字:关闭信号可能会在最后一个数据仍在传输之前破坏连接。
确保同伴正确接收的正确方法是graceful shutdown。
答案 1 :(得分:3)
TCP / IP是可靠的,对于单词&#34;可靠&#34;的非常特殊(和有限)的含义。
具体来说,当write()返回1000000时,它会使你获得以下承诺:
但也有一些保证,write()不会(并且,通常,不能)提供。特别是:
请注意,在上面列出的所有情况中,write()返回后都会出现问题,这就是为什么write()只能在发生错误代码时返回错误代码的原因。 (稍后调用write()可能会返回错误代码,当然,这不会特别帮助您知道传递字节和未传递字节之间的界限位于何处)
TLDR:TCP / IP比UDP更可靠,但不是100%的铁壳保证不会出错。如果您确实希望确保在接收端处理了您的字节,那么您将要对您的接收应用程序进行编程,以便发回某些更高级别的确认,表明它已收到(并成功处理!)您发送的字节它
答案 2 :(得分:2)
TCP / IP 提供可靠性,这意味着它允许重传丢失的数据包,从而确保(最终)接收到的所有数据或您获得超时错误。要么你的东西交付,要么你出现超时错误
What is the correct way of reading from a TCP socket in C/C++?
和顺便说一下,TCP / IP在某种程度上是可靠的,它可以保证在网络正常工作的情况下交付......如果你拔掉电缆,TCP / IP将无法提供你的数据包
P.S。你应该至少将指针推进buffer
缓冲区
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;
}
}
答案 3 :(得分:2)
计划A报告所有数据都已正确发送!
没有。程序A中write
的返回仅表示返回的字节数已经传递给操作系统的内核。它并未声称数据已由本地系统发送,已被远程系统接收或甚至已由远程应用程序处理。
我相信TCP是可靠的。
TCP仅在传输层提供可靠性。这意味着它只能确保检测到数据丢失(并重新发送数据包),检测到数据复制(并丢弃重复数据),并检测并修复数据包重新排序。
TCP没有要求任何更高层的可靠性。如果应用程序需要它,则必须由应用程序本身提供。