unix network programming(3rd)Vol.1 [第16~22章]《读书笔记系列》

第16章 非阻塞式IO

各个操作系统的非阻塞IO是不一样的。不可移植。 (试试看下golang)

socket 套接字默认是阻塞的。

可能阻塞的socket 分为4类
1.输入操作
read、readv、recv、recvfrom、recvmsg 5个函数

2.输出操作
write、writev、send、sendto、sendmsg 5个函数

3.接收外来连接
accept 函数

4.发起外出连接
connect 函数

以上所有操作函数, 可以通过Fcntl()把FD设置 为 非阻塞。

socketfd/标准输入/标准输出 都可以设置为非阻塞。

  • 这里分析了str_lic的执行时间,看各个版本的优劣。

    阻塞 等停版本: 354s 耗费时间长
    select 加阻塞I/O版本: 12.3s 简单
    非阻塞I/O 版本: 6.9s 代码量大,复杂度高,容易出问题
    fork 版本: 8.7s 简单,耗费资源多
    thread 版本: 8.5s 简单

16.3 非阻塞connect

flasgs = Fcntl(sockfd, F_GETFL, 0);
Fcntl(sockfd, F_SETFL, flags | o_NONBLOCK);
...
connect(sockfd, saptr, salen);
...
select(sockfd+1, &rset, &wset,NULL, nsec?&tval:NULL);

16.4 非阻塞connect:时间获取客户端

封装了一个connect_bonb()函数

16.5 非阻塞connect:web客户端

16.6 非阻塞accpet

当有一个已完成的连接准备好accpet时,select将作为可读描述符 返回该连接的监听套接字。
因此,如果我们使用select在某个监听套接字上等待一个外来连接,那就没有必要把该套接字设置非阻塞,因为如果select告诉我们该套接字上已有连接就绪,
那么随后的accpet调用不应该阻塞。

一旦建立连接,设置SO_LINGER套接字选项,把l_onoff设1,把l_linger时间设0,
如7.5节 中说的那样
这样导致连接被关闭时在TCP套接字上发送一个RST。 我们随后关闭该套接字。

#include "unp.h" //大写字母的 函数是自己定义的

int sockfd;
struct linger ling;
struct sockaddr_in servadr;
...
sockfd = Socket(AF_INET, SOCK_STREAM, 0);

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
Connect(sockfd, (SA*) &servaddr,sizeof(servaddr));
ling.l_onoff = 1;//case RST to be sent on close()
ling.l_linger = 0;

Setsockopt(sockfd, SOL_SOCKET, SOLINGER , &ling, sizeof(ling));
Close(sockfd);
...

如果服务器繁忙,无法在select返回监听套接字的可读条件后,就马上调用accpet。 然后接收到客户端的RST, 这就出现了问题。
已完成连接 被服务器TCP驱逐出队列,
服务器调用accpet,但是没有任何已完成队列的连接,导致服务器阻塞。

解决办法:
1)当使用select 获取某个监听套接字上 何时有已完成连接,准备好被accpet时,总是把这个套接字 设为非阻塞。
2) 在后续的accpet调用中忽略以下错误 :
EWOULDBLOCK (berkeley 实现,客户终止连接时)、
ECONNABORTED(POSIX 实现,客户终止连接时)、
EPROTO(SVR4 实现,客户终止连接时)、
和EINTR(如果有信号被捕获)

非阻塞conncet 能使我们 在TCP握手发生期间做其他处理,而不是阻塞在connect。

同时打开多个连接可以减少单个服务器取得多个文件所需要的时间的web 客户端,如此发起多个连接可以减少时间,不过考虑到 TCP的拥塞避免机制,对网络消耗太大。

根据实际情况 ,慎重使用

第17章 ioctl 操作(重点)

#include <unistd.h>
int ioctl(int fd, int request,... /* void *arg */ ) //return:成功返回0,错误返回-1

fd 是引用一个打开文件的描述符
第三个参数是一个指针,指针类型 依赖于request参数。

网络相关的请求分6类:

  • 套接字操作
  • 文件操作
  • 接口操作
  • ARP告诉缓存操作
  • 路由表操作
  • 流系统(第31章)

网络程序(特别是服务器)在程序启动后执行 ioctl 获取主机 全部网络接口信息。 包括: 接口地址,是否支持广播,是否支持多播,等

第18章 路由套接字(重点)

第19章 密钥管理套接字

第20章 广播

第21章 多播

第22章 高级UDP套接字编程

posted @ 2015-11-06 00:33  scott_h  阅读(271)  评论(0编辑  收藏  举报