2017-04-13 71 views
2

这是我的理解,如果写入的数据量很小,写入TCP/IP套接字将是原子。原子,我的意思是接收器将接收所有的数据或不接收数据。但是,如果写入的数据量很大,则不是原子的。我对么?如果是这样,什么重要?TCP/IP套接字是否原子?

感谢, 鲍勃

+1

鲍勃,你的问题很好,许多程序员有错误,他们认为如果他们在TCP套接字中发送N个字节,另一个节点将读取全部N个字节。然后,他们运行功能测试并开始工作。但是,这是一个在某个时刻会在系统中产生故障的错误。你想要做的是创建一个简单的应用层协议,通常是TLV(Type,Length,Value)。我在这里解释它(这个问题适用于任何编程语言):http://stackoverflow.com/questions/19839172/how-to-read-all-of-inputstream-in-server-socket-java/19863726#19863726 – rodolk

回答

1

对于UDP,这是真的,因为应用程序写入的所有数据在一个UDP数据包发送出去。

对于TCP,事实并非如此,除非应用程序一次只发送1个字节的数据。写入TCP套接字会将所有数据写入与该套接字关联的缓冲区。然后,TCP将在后台从该缓冲区读取数据并将其发送到接收器。多少数据TCP实际上发送在一个TCP段取决于其流控制机制的变量和其它因素,包括:

  • ,接收所述其它节点(接收器)公布的窗口数据的
  • 金额先前发送在飞行段还未被确认
  • 慢启动和拥塞避免算法状态
  • 协商的最大段大小(MSS)

在TCP,你永远无法assum e应用程序写入套接字的内容实际上是由接收器读取的。套接字缓冲区中的数据可以在一个或多个TCP段中发送到接收器。在数据可用的任何时刻,接收者可以执行套接字读取并返回当前实际可用的任何数据。

当然,所有发送的数据最终都会到达接收方,如果中间没有故障阻止,并且接收方在数据到达之前没有关闭连接或停止读取。

+1

“*,除非应用程序一次只发送1个字节的数据*” - 即使这不是保证,因为数据默认被缓冲。除非启用'TCP_NODELAY'套接字选项,否则可以执行多个1字节写入操作,并仍然将它们一起发送到单个TCP段中。 –

+1

而且无论如何,您仍然可以*在一次接收操作中*接收*它们。 @RemyLebeau – EJP

+0

@EJP:是的,如果在应用程序执行新的读取操作之前接收并缓冲了套接字中的多个TCP段。 –

2

No. TCP是一种字节流协议。没有消息,没有类似数据报的行为。

+0

根据我收到的响应,如果服务器写入一个四字节整数并且客户端读取一个四字节整数,则读取可能只返回两个字节,因为写入不是原子的,随后的读取将返回另外两个字节。我有这个权利吗?鲍勃。 – Bob

+0

@鲍勃,这是正确的。 – rodolk