1-- 循环服务器模型
tcp 循环服务器
udp 循环服务器
2-- 并发服务器
tcp 并发服务器
父子进程实现并发服务器:
父亲进程 ,接收请求。accept
儿子进程 ,处理具体客户端需求。send / recv
注意点:僵尸进程,父亲活着,儿子死亡,父亲没有为儿子进程收尸,会产生僵尸进程。
避免僵尸进程:
1、儿子活着,父亲死亡。
2、父亲回收儿子进程的尸体
wait/waitpid()
3、儿子死亡,父亲也死亡。系统回收僵尸进程
信号:
signal();
回收资源,应该在信号处理函数中进行。
select 实现并发服务器:
监听 sockfd 、acceptfd
ggVC 全部复制
【2】网络属性
int getsockopt(int sockfd, int level, int optname,
void *optval, socklen_t *optlen);
功能:获取网络套接字的属性信息
参数:sockfd 网络套接字
level SOL_SOCKET 应用层
IPPROTO_TCP 传输层
IPPROTO_IP IP选项.
optname SO_BROADCAST 广播
SO_REUSEADDR 允许重复绑定
SO_SNDBUF 获取发送缓存区大小的命令
SO_RCVBUF 接收缓存区大小的命令
SO_RCVTIMEO 超时检测
optval 操作的值
optlen 值的大小
返回值:成功 0
出错 -1
int setsockopt(int sockfd, int level, int optname,
const void *optval, socklen_t optlen);
功能:设置网络套接字的属性信息
参数:sockfd 网络套接字
level SOL_SOCKET 应用层
IPPROTO_TCP 传输层
IPPROTO_IP IP选项.
optname SO_BROADCAST 广播
SO_REUSEADDR 允许重复绑定
SO_SNDBUF 获取发送缓存区大小的命令
SO_RCVBUF 接收缓存区大小的命令
SO_RCVTIMEO 超时检测
optval 操作的值
optlen 值的大小
返回值:成功 0
出错 -1
【3】网络超时检测
在网络通信中,很多操作会使得进程阻塞
TCP套接字中的recv/accept/connect
UDP套接字中的recvfrom
超时检测的必要性
避免进程在没有数据时无限制地阻塞
当设定的时间到时,进程从原操作返回继续运行
1-- 使用setsockopt 设置超时时间。
struct timeval tv;
52 tv.tv_sec = 5;
53 tv.tv_usec = 0;
54
55 if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
56 {
57 err_log("fail to setsockopt.");
58 }
2-- 使用select 实现 超时检测
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
struct timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 10;
if((ret = select(maxfd+1, &readfds, NULL, NULL, &tv)) < 0)
注意点:每次select 之前,都需要对时间重新赋值
3-- 使用 alarm 定时器,实现超时检测
int sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);
功能:实现信号的注册和信号属性的修改
参数:signum 信号
act 信号的新属性
oldact 信号的旧属性
返回值:成功 0
出错 -1
struct sigaction {
void (*sa_handler)(int); // 信号处理函数
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags; // 自重启属性标志位,信号默认时为真,要设为假
void (*sa_restorer)(void);
};
struct sigaction act;
sigaction(SIGALRM, NULL, &act);
act.sa_handler = handler;
act.sa_flags &= ~SA_RESTART; // 将信号的自重启属性设为假
sigaction(SIGALRM, &act, NULL);
自重启属性:当一个信号产生时,进程会去执行信号处理函数,信号处理函数执行完毕,进程会接着
原来的点,继续向下执行。(这叫做自重启属性为真)