《TCP/IP网络编程》尹圣雨 P211-P225
send & recv函数
Linux中的send & recv
#include<sys/socket.h>
ssize_t send(int sockfd, const void *buf,size_t nbytes,int flags);
成功时返回发送的字节数,失败时返回-1.
#include<sys/socket.h>
ssize_t recv(int sockfd, void *buf,size_t nbytes,int flags);
成功时返回接收的字节数(收到EOF返回0),失败时返回-1.
send函数和recv函数的最后一个参数是收发数据时的可选项。该可选项可利用位或运算同时传递多个信息、
send、recv函数的可选项及含义
MSG_OOB :用于传输带外数据 Out-of-band data
MSG_PEEK:验证输入流缓冲中是否存在接收的数据
MSG_DONTROUTE:数据传输过程中不参照路由表Routing,在本地Local网络中寻找目的地
MSG_DONTWAIT:调用I/O函数时不阻塞,用于使用非阻塞Non-blocking I/O
MSG_WAITALL:防止函数返回,直到接收全部请求的字节数
MSG_OOB发送紧急消息
用于发送“带外数据”的紧急消息、用于创建特殊发送方法和通道以发送紧急消息、
fcnt1(recv_sock, F_SETOWN, gitpid());
fcnt1函数用于控制文件描述符,含义如下:“将文件描述符recv_sock指向的套接字拥有者(F_SETOWN)改为把getpid函数返回值用于ID的进程”。
注:操作系统实际创建并管理套接字,“套接字拥有者”是操作系统。此处的“拥有者”是指负责套接字所有事物的主体。
文件描述符recv_sock指向的套接字印发的SIGURG信号处理进程变为将getpid函数返回值用作ID的进程。
多个进程可以共同拥有1个套接字的文件描述符。
通过MSG_OOB可选项传递数据时,不会加快数据传输速度,而且通过信号处理函数读取数据只能读1个字节。MSG_OOB含义OUT-OF-DATA,"带外数据",指的是“通过完全不同的通信路径传输的数据”。
真正意义上的Out-pf-band需要单独的通信路径高速传输数据,但TCP不另外提供,只利用TCP的紧急模式进行传输。
紧急模式工作原理
MSG_OOB的意义在于督促数据接收对象尽快处理数据。
紧急消息传输阶段的输出缓冲 | ||||||
8 | 9 | 0 | . | . | . | . |
偏移量0 |
|
| 偏移量3 |
|
|
|
将缓冲最做到的位置视作偏移量为0,字符0保存于偏移量为2的位置。偏移量3的位置存有紧急指针UrgentPointer.紧急指针指向紧急消息的下一个位置(偏移量加1),同时向对方主机传递如下信息:紧急指针指向的偏移量为3之前的部分就是紧急消息。
实际上只有1个字节表示紧急消息。
设置URG的数据包 | |||
URG=1,URG指针=3 | 8 | 9 | 0 |
TCP头 | 数 | 数 | 数 |
TCP头中含有如下两个消息:
URG=1:载有紧急消息的数据包
URG指针:紧急指针位于偏移量为3的位置。
指定MSG_OBB选项的数据包本身就是紧急数据包,并通过紧接指针表示紧急消息所在位置。
注意:偏移量就是参照基准位置表示相对位置的量。偏移量表示距离基准点向那个方向偏移多长距离。偏移地址每次从0开始。
检查输入缓冲
同时设置MSG_PEEK和MSG_DONTWAIT选项,以验证输入缓冲中是否存在接收的数据。设置MSG_PEEK选项并调用recv函数时,即使读取了输入缓冲数据也不会删除。该选项通常与MSG_DONTWAIT合作,用于调用以非阻塞方式验证待读取数据存在与否的函数。
readv & writev函数
使用readv & writev函数
功能:对数据进行整合传输及发送的函数。
通过writev函数可以吧分散保存在多个缓冲中的数据一并发送,通过readv函数可以由多个缓冲分别接收。适当使用2个函数可以减少I/O函数的调用次数。
#include<sys/uio.h>
ssize_t writev(int filedes, const struct iovec *iov, int iovcnt);
成功时返回发送的字节数,失败返回-1
filedes:表示数据传输对象的套接字文件描述符。该函数并不只限于套接字,因此,可以像read函数一样向其传递文件或标准输出描述符。
iov:ioves结构体数组的地址值,结构体iovec中包含待发送数据的位置和大小信息。
iovcnt:向第二个参数传递数组长度。
struct iovec {
void * iov_base;//缓冲地址
size_t iov_len;//缓冲大小
};
下面介绍readv函数,与writev函数正好相反。
#include<sys/uio.h>
ssize_t readv(int filedes, const struct iovec *iov, int iovcnt);
成功时返回发送的字节数,失败返回-1
合理使用readv & writev函数
从
C
角度看,减少函数调用次数也能相应提高性能,但其更大意义在于减少数据包个数。