Socket被创建后(这里先是指TCP)。都会分配两个缓存区,一个输入缓存区,一个输出缓存区。write()和send()并不是立即向网络中传输数据,二叔先把数据写到缓存区。写进去,函数就返回成功了,什么时候发,都是TCP协议负责的事情。
TCP协议独立于 write()/send() 函数,数据有可能刚被写入缓冲区就发送到网络,也可能在缓冲区中不断积压,多次写入的数据被一次性发送到网络,这取决于当时的网络情况、当前线程是否空闲等诸多因素,不由程序员控制。
输入输出缓冲区的默认大小一般都是 8K,可以通过 getsockopt() 函数获取:
TCP有黏包的特性
默认情况下,close()/closesocket() 会立即向网络中发送FIN包,不管输出缓冲区中是否还有数据,而shutdown() 会等输出缓冲区中的数据传输完毕再发送FIN包。也就意味着,调用 close()/closesocket() 将丢失输出缓冲区中的数据,而调用 shutdown() 不会。
CPU向内存保存数据的方式有两种:
大端序(Big Endian):高位字节存放到低位地址(高位字节在前)。
小端序(Little Endian):高位字节存放到高位地址(低位字节在前)。
图来自http://c.biancheng.net/cpp/html/3047.html
不同CPU保存和解析数据的方式不同(主流的Intel系列CPU为小端序),小端序系统和大端序系统通信时会发生数据解析错误。因此在发送数据前,要将数据转换为统一的格式——网络字节序(Network Byte Order)。网络字节序统一为大端序。