可能一两句话说不清,关闭了吧。
当客户端链接到服务器端,client socket fd
如何传入到accept
方法里面去的?
在循环服务器中
accept(lfd, (struct sockaddr *)&clin_addr, &clin_len)
为什么当有客户端连接的时候,客户端的sockaddr_in
数据就能会被服务器识别赋值到clin_addr
呢?然后传入上面的accept
方法。
当有预先分配了很多子进程做accept
等待,那么新进来的客户端是如何被主线程分配给这些子线程的呢?
// sockfd 是主线程中监听的套接字
for(i = 0; i < 3; i++){
pid[i] = fork();
if(pid[i] == 0)
handle_fork(sockfd);
}
...
// 子线程做 accpet 阻塞等待
static void handle_fork(int sockfd){
int newfd;
struct sockaddr_in c_addr;
char buf[BUFLEN];
socklen_t len;
time_t now;
while(1){
len = sizeof(struct sockaddr);
accept(sockfd,(struct sockaddr*) &c_addr, &len)
...
close(newfd);
}
}
如果上面伪代码能否表述清楚,可以看下我做的这个笔记http://mengkang.net/576.html#server02
第一次见到这样的代码,想法挺好的,但是我们更倾向于创建线程,节省资源。
简单来说
当进程执行到accept
意思是请求返回一个TCP链接的描述符,就是说请求一个资源。如果没有操作系统会挂起这个进程,所以这几个子进程都会挂起。
操作系统会分配一个信号量S(就是一个整数,记录有几个链接)。进程执行到accept的时候各个进程会互斥的执行S=S-1,如果大于等于0就继续执行,否则挂起等待操作系统调度。有链接进来就操作系统会S=S+1,如果S>=0,线程继续执行,否者,从挂起的进程中根据线程优先级和等待的时间从中唤醒一个进程。让进程可以有机会继续执行。
多个进程监听同一个描述符,加入了队列中,每次进来新连接时,唤醒第一个进程处理