Linux socket 高级主题

本文深入探讨了Linux套接字的高级主题,包括部分读写、shutdown()调用、recv()和send()系统调用、sendfile()、TCP_CORK选项以及TCP协议的细节,如序列号、确认机制、状态机等。通过了解这些概念,开发者可以更好地理解和利用Linux套接字进行网络通信。
摘要由CSDN通过智能技术生成

以下内容引述自《Linux/Unix系统编程手册》

流式套接字上的部分读和部分写

如果套接字上可用的数据比在read()调用中请求的数据要少,这种情况下,read()直接返回可用的字节数。
如果没有足够的缓冲区空间来传输所有请求的字节,并且满足了如下的几条中的其中一条时,可能会出现部分写的现象。

  • 在write() 调用中传输了部分请求的字节后被信号处理例程中断;
  • 套接字工作在非阻塞模式下(O_NONBLOCK),可能当前只能传输一部分请求的字节;
  • 在部分请求的字节已经完成传输后出现了一个异步错误。对于这里的异步错误,我们指的是应用程序使用的套接字API调用中出现了一个异步错误。异步错误是可能会发生的

在所有上述情况中,假设缓冲区空间至少能传输1字节数据,write()调用成功,并返回传输到输出缓冲区中的字节数。
如果出现了部分I/O现象——例如,如果read()返回的字节数少于请求的数量,又或者是阻塞式的write()调用在完成了部分数据传输后被信号处理例程中断——那么有时候需要重新调用系统调用来完成全部数据的传输。
针对以上情况,我们使用循环调用系统函数来重新启用这些系统调用,因此确保了请求的字节数总是能够全部得到传输

shutdown()系统调用

在套接字上调用close() 会将双向通信通道的两端都关闭。有时候,只关闭连接的一端也是有用处的,这样数据只能在一个方向上通过套接字传输。系统提供了shutdown()提供了这种功能。

#include <sys/socket.h>
int shutdown(int sockfd, int how);

系统调用shutdown()可以根据参数how的值选择关闭套接字通道的一端还是两端。参数how可以选择以下几种:
SHUT_RD
关闭连接的读端。之后的读取操作将返回文件结尾(0)。数据仍然可以写入到套接字上。在UNIX域流式套接字上执行了SHUT_RD操作后,对端应用程序将接收到一个SIGPIPE信号,如果继续尝试在对端套接字上做写操作的话,将产生EPIPE错误。
SHUT_WR
关闭连接的写端。一旦对端的应用程序已经将所有剩余的数据读取完毕,它就会检测到文件结尾。后续对本地套接字的写操作将产生SIGPIPE信号以及EPIPE错误。而由对端写入的数据仍然可以在套接字上读取。
SHUT_RDWR
将连接的读端和写端都关闭。这等同于先执行SHUT_RD,跟着再执行SHUT_WR操作

shudown() 同close() 之间的另一个重要区别是:无论该套接字上是否还关联着其他的文件描述符,shutdown()都会关闭套接字通道。但是shutdown()并不会关闭文件描述符,就算参数how指定为SHUT_RDWR时也是如此。要关闭文件描述符,必须另外调用close()

专用于套接字的I/O系统调用:recv和send

recv() 和 send() 系统调用可在已连接的套接字上执行I/O操作。提供了专属于套接字的功能,而这些功能在传统的read() 和 write() 系统调用中是没有的。

#include <sys/socket.h>
ssize_t recv(int sockfd, void *buffer, size_t length, int flags);
ssize_t send(int sockfd, void *buffer, size_t length, int flags);

recv() 和 send() 的返回值以及前3个参数同read() 和 write() 一样。最后一个参数flags 是一个位掩码,用来修改 I/O 操作的行为。
对于recv() 来说,该参数可以为下列值相或的结果
MSG_DONTWAIT
让recv() 以非阻塞方式执行。如果没有数据可用,那么recv()不会阻塞而是立刻返回,伴随的错误码为EAGAIN。我们可以通过fcntl()把套接字设为非阻塞模式(O_NONBLOCK) 从而达到相通的效果。区别在于MSG_DONTWAIT允许我们在每次调用中控制非阻塞行为
MSG_OOB
在套接字上接收带外数据
MSG_PEEK
从套接字缓冲区获取一份请求字节的副本,但不会请求的字节从缓冲区中实际移除,这份数据稍后可以由其他的recv()或read()调用重新读取
MSG_WAITALL
通常,recv() 调

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值