《TCP/IP网络编程》第13章 笔记&代码&注释

在之前我们Windows使用了很多次的send()和recv()来进行数据的收发,但我们并未向最后一个参数传递过 0 之外的参数。

另外还有许多I/O函数

多种I/O函数

在Linux中的send() & recv()

最后一个参数是为了指定可选项信息,在之前并未向其传递0之外的参数。

可传递参数包括以下但不止这些:

  • MSG_OOB 传输带外数据(优先传输)
  • MSG_PEEK 验证输入缓冲中是否存在接受的数据
  • MSG_DONTROUTE 数据传输过程中不参照路由表(routing)而在本地(local)王志忠寻找目的地
  • MSG_DONTWAIT 调用I/O函数时不阻塞,用于非阻塞函数
  • MSG_WAITALL 防止函数返回,直至接受全部请求的字节数

MSG_OOB

客户端(Client)用于发送带外数据紧急消息:

//Client
write(sock,"123",strlen("123"));
send(sock,"4",strlen("4"),MSG_OOB);
write(sock,"567",strlen("567");
send(sock,"890",strlen("890"),MSG_OOB);

客户端按照顺序,理应是123 4 567 890 地接收,但因为紧急传输了4 890 接收顺序也因此改变。

注:紧急消息的意义在于督促消息处理而非金及传输形式受限的消息。

MSG_PEEL & MSG_DONTWAIT

MSG_PEEL & MSG_DONTWAIT 同时输入两个选项,已验证输入缓冲中是否存在接受的数据。

设置MSG_PEEK并调用recv(),即使读取了输入缓冲中的数据也不会删除(仅做检查),因此该选项常与MSG_DONTWAIT合作,用于调用一非阻塞方式验证待读数据是否存在。

//peek_recv

recv(recv_sock,buf,sizeof(buf-1), MSG_PEEK|MSG_DONTWAIT);

 

readv() & writev()

readv()& writev()  对数据进行整合传输发送的函数。

通过writevI()可以将分散保存的多个缓冲区数据一并发送,通过readv由多个缓冲区分别接收数据。

也称:散布读(scatter read)和聚集写(gather write)。

//Linux
struct iovec
{
    void * iov_base;
    size_t iov_len;
}

int main()
{
    //...
    struct iovec vec[2];
    char buf1[]="abcde";
    char buf2[]="ghijk";
    int strlen;
    
    vec[0].iov_base=buf1;
    vec[0].iov_len=sizeof(buf1);
    vec[1].iov_base=buf2;
    vec[1].iov_len=sizeof(buf2);

    str_len=writev(1,vec,2);
    //...
}

writev( filedes , ptr , 2 );

首参是文件描述符,ptr是待发送数据iovec数据信息的数组指针,2表示从ptr指向位置开始至浏览两个iovec结构体变量,并发送这些指针指向的缓冲数据。

readv()则将读入的数据按上述同样顺序散布到缓冲区中。readv总是先填满一个缓冲区,然后再填写下一个。readv返回读到的总字节数。如果遇到文件结尾,已无数据可读,则返回0。

合理使用readv() & writev()

(Linux)多次调用read和write的情况可以使用一次readv和writev代替,在C语言角度,减少函数调用次数能提高性能,但这不止减少数据包个数:在为了提高效率,服务器命令禁止Nagle算法情况下,writev函数在不采用Nagle算法时更有价值。

基于Windows的实现

在Windows中不存在Linux那样的信号处理机制!

回顾12章select监视3个对象:

  • 是否存在套接字接收数据?
  • 无需阻塞传输数据的套接字有哪些?
  • 哪些套接字发生了异常?

其中“异常”指不同寻常的程序执行流,因此,Out_of_band数据也属异常。因此可以利用select()这一特性在Windows中接收Out_of_band数据,实际发送(send)代码与上面Linux无异(但首参的数据类型是SOCKET代表目标的套接字)。

不同的是接收紧急消息的代码:

代码:

https://github.com/ChristmasError/TCP-IP-Network-programming/tree/master/%E7%AC%AC%E5%8D%81%E4%B8%89%E7%AB%A0%20%E5%A4%9A%E7%A7%8DIO%E5%87%BD%E6%95%B0

关于Windows的readv() & writev()

windows并无函数与Linux的readv() & writev()直接对应,但可以通过 重叠I/O 得到相同的效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值