Skip to content
forked from DingHe/unpv13e

UNIX网络编程 卷1:套接字联网API(第3版)源代码

Notifications You must be signed in to change notification settings

arkingc/unpv13e

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

72 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

UNIX网络编程 卷1:套接字联网API(第3版)源代码

TCP回射服务器 v1 客户端 str_cli函数(阻塞于标准输入时无法处理来自服务器子进程的FIN分节)
服务器(多进程) 服务器会产生僵尸子进程
v2 服务器(多进程) 处理服务器僵尸子进程,会中断服务器系统调用
v3 服务器(多进程) 处理服务器被中断的系统调用,无法同时处理多个SIGCHLD信号
v4 客户端 正常终止时引起服务器5个子进程终止
服务器(多进程) 同时处理多个SIGCHLD信号
select 客户端 str_cli函数(解决v1版的问题,但无法处理重定向、无法处理I/O缓冲)
客户端 str_cli函数(解决前一版的问题)
服务器(单进程) 重写v4版服务器,使用单进程减少了多进程的开销
poll 服务器(单进程) 重写v4版服务器,使用单进程减少了多进程的开销
总结 v1-v4:正确处理服务器终止的子进程
UDP回射服务器 v1 客户端 dg_cli函数(v1)
问题一:任何进程可向客户端发数据,会与服务器的回射数据报混杂
问题二:客户数据报或服务器应答丢失会使客户永久阻塞于recvfrom
问题三:服务器未启动会使客户端阻塞于recvfrom
服务器(单进程) dg_echo函数
v2 客户端 dg_cli函数(v2)
处理问题一,验证接收到的响应。但无法处理服务器多宿(多个IP)的情况
v3 客户端(connect版) dg_cli函数(v3)
v4 客户端 dg_cli函数(v4):写2000个1400字节的UDP数据报给服务器
问题:UDP缺乏流量控制,服务器接收速率慢时,缓冲区被发送端淹没
服务器(单进程) dg_echo函数
v5 服务器(单进程) dg_echo函数(增大接收缓冲区的大小)
总结 v1:问题二、三的根本原因是UDP数据传输不可靠
v4-v5:UDP缺乏流量控制,服务器接收的数据报数目不定,依赖诸多因素

宏值与头文件表:

常量 所在头文件
SERV_PORT 9877 unp.h
MAXLINE 4096 unp.h

可以调用sigaction函数来检查或修改与指定信号相关联的处理动作。传入“信号处理函数”,只要有信号发生,信号处理函数就会被调用,这种行为称为“捕获信号”

/*
 *  参数:
 *      signo:要检测或修改其具体动作的信号编号
 *      act:非空,则要修改其动作
 *      oact:非空,则经由oact返回该信号的上一个动作
 */
int sigaction(int signo,const struct sigaction *restrict act,
            struct sigaction *restrict oact);

struct sigaction {
    void (*sa_handler)(int);    //信号处理函数的地址,或SIG_IGN、SIG_DFL
    //在调用信号处理函数之前,信号集要加到进程的信号屏蔽字中。
    //仅当从信号处理函数返回时再将进程的信号屏蔽字恢复为原先值。
    //这样,在调用信号处理函数时就能阻塞某些信号。在信号处理程序被调用时,
    //操作系统建立的新信号屏蔽字包括正被传递的信号。因此保证了在处理一个
    //给定的信号时,如果这种信号再次发生,那么它会被阻塞到对前一信号的处理
    //结束为止。如果一个信号在被阻塞期间产生了一次或多次,那么该信号被解
    //阻塞之后通常只递交一次,也就是说UNIX信号默认是不排队的
    sigset_t sa_mask;           //阻塞额外的信号
    int sa_flags;               //信号标志
    void (*sa_sigaction)(int,siginfo_t *,void *);
}

//信号处理函数,传入信号值
void handler(int signo);    //可以将信号值设为SIG_IGN来忽略它;设为SIG_DFL来启用默认处置
  • 忽略信号:将handler的参数设为SIG_IGN来忽略对某个信号的处置
  • 启用信号的默认处置:将handler的参数设为SIG_DFL来启动信号的默认处置
    • 默认处置通常是收到信号后终止进程
    • SIGCHLD和SIGURG(带外数据到达时发送)的默认处置是忽略信号
信号 描述
SIGCHLD 子进程终止时给父进程发送的信号,如果父进程没有捕获代码,则这个信号被忽略
SIGTERM 关机时,init进程向系统中进程发出的信号,提示进程即将关机,进程可以捕获然后执行一些处理
SIGKILL(不能捕获) 杀掉进程
SIGSTOP(不能捕获) 停止进程
信号标志 描述
SA_RESTART 如果设置,由相应信号中断的系统调用将由内核自动重启(但是好像某些实现即使支持这个标志,也不一定会重启,所以不能过分依赖这个标志)

Linux环境下开发经常会碰到很多错误(设置errno),常见错误:

错误 描述
EAGAIN 通常发生在非阻塞I/O中,如果数据未准备好,I/O操作会返回这个错误,提示再试一次
EINTR 表示系统调用被一个捕获的信号中断,发生该错误可以继续读写套接字

About

UNIX网络编程 卷1:套接字联网API(第3版)源代码

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C 69.9%
  • Roff 22.9%
  • Shell 4.3%
  • Makefile 2.6%
  • C++ 0.3%