Unix Network Programming 1

卷一主要以TCP echo服务为例,对UNIX网络socket编程做了讲解。

基本TCP socket编程

使用socket, connect, bind, listen, accpet, fork, exec, close等基本函数搭建一个并发服务器。

然后讨论了多种异常情况,包括:

  1. accept返回前终止

  2. 服务器进程终止
    服务器会向客户TCP发送FIN,客户在socket会读取到EOF

  3. 服务器崩溃
    这时服务器不会发送FIN,客户TCP会不断尝试重传直到超时。可以使用SO_KEEPALIVE和超时机制探测服务器状态

  4. 服务器崩溃后重启
    客户TCP向服务器发送数据时,服务器由于不存在这个TCP连接,会向客户发送RST

IO复用

讲解了select和poll函数实现IO复用

套接字选项

重点选项:

  1. SO_REUSEADDR
    所有服务器套接字都应该使用这个选项,用以部分解决TIME_WAIT的问题

  2. SO_LINGER
    用以决定close后缓冲区中残留数据的处理方式。l-onoff设为非0,且l_linger为0时,close将导致缓冲区中的数据被扔到并向对端发送RST,也可以避免TIME_WAIT

  3. SO_KEEPALIVE
    TCP保活机制

基本UDP socket编程

UDP编程与TCP编程类似,但是由于UDP没有状态,不需要建立连接。

对UDP而言,可以直接使用recvfrom和sendto发送数据。也可以先connect,只不过这个connect并不真正建立连接,只是检查目标是否可达。另外,已连接的UDP可以使用read/write函数读写数据。

Unix域 socket编程

使用unix域socket的理由之一是,通过unix域socket可以传递描述符。

使用socketpair创建unix域socket,其他函数类似。

C/S设计范式

卷一的最后给出了一系列C/S设计范式,并对其性能进行了对比。

  1. TCP迭代服务器

  2. TCP并发服务器,每个客户一个子进程
    通过fork为每个客户分配一个子进程,但是由于进程创建开销较大,这种服务器效率并不高

  3. TCP并发服务器,预先fork子进程,子进程accept,无锁保护
    预先fork子进程,子进程阻塞在accept上由内核进行schedule。由于惊群(TCP连接时,多个子进程被唤醒争夺accept),如果子进程过多,则会比较影响效率

  4. TCP并发服务器,预先fork子进程,子进程使用文件上锁/线程上锁
    通过用户级的锁降低冲突

  5. TCP并发服务器,主进程传递socket描述符到子进程

  6. TCP并发服务器,使用线程替代进程