linux多进程监听同一个端口,linux 系统实现多个进程监听同一个端口(会有惊群)...

linux 系统实现多个进程监听同一个端口

通过 fork 创建子进程的方式可以实现,其他情况下不行。

当连接到来时,子进程、父进程都可以 accept, 这就是著名的“惊群”问题(thundering herd problem)。

惊群现象

在该模型下(多个子进程同时共享监听套接字)即可实现服务器并发处理客户端的连接。这里要注意的是,计算机三次握手创建连接是不需要服务进程参数的,而服务进程仅仅要做的事调用accept将已建立的连接构建对应的连接套接字connfd(可参考 http://blog.csdn.net/ordeder/article/details/21551567)。多个服务进程同时阻塞在accept等待监听套接字已建立连接的信息,那么当内核在该监听套接字上建立一个连接,那么将同时唤起这些处于accept阻塞的服务进程,从而导致“惊群现象”的产生,唤起多余的进程间影响服务器的性能(仅有一个服务进程accept成功,其他进程被唤起后没抢到“连接”而再次进入休眠)。

一直疑惑一个应用app如何才能以多进程,多线程的方式运行。对于多线程可能很好理解,我们只要在进程中启用多线程的模式即可。也就是来一个请求,我们就用函数pthread_create()启用一个线程即可。这样我们的应用就可以在单进程,多线程的模式下工作。

但我们知道一个应用app通常工作在多进程,多线程的模式下,它的效率是最高的。那么我们如何才能做到多进程模式呢?经验告诉我们,如果多次启动一个进程会报错:“Address already in use!"。这是由于bind函数导致的,由于该端口号已经被监听了。

其实我们只要在绑定端口号(bind函数)之后,监听端口号之前(listen函数),用fork()函数生成子进程,这样子进程就可以克隆父进程,达到监听同一个端口的目的。好了,废话不多说,我们看一下具体代码。

server.c

#include

#include

#include

#include

#include

#include

#defineoops(m){perror(m); exit(1);}

intmain(){

intsock_id;

structsockaddr_insaddr;

sock_id = socket(PF_INET, SOCK_STREAM, 0);

saddr.sin_addr.s_addr = inet_addr("127.0.0.1");

saddr.sin_port = htons(9988);

saddr.sin_family = AF_INET;

int ret = bind(sock_id, (struct sockaddr *) &saddr, sizeof(saddr));//绑定IP地址和端口

if(ret == -1) oops("bind error");//如果返回-1,则绑定失败,一般为“Address alreay in use”

inti;

for(i = 0; i < 6; i++){//连续创建六个子进程

int pid = fork();

if(pid == 0) break;

}

listen(sock_id, 1);

while(1){

intsock = accept(sock_id, NULL, 0);

char buf[128];

intreadnum;

readnum = read(sock, buf, 127);

buf[readnum] = '\0';

printf("pid=%d, mesg: %s\n", getpid(), buf);

fflush(stdout);

close(sock);

}

return 1;

}

client.c

#include

#include

#include

#include

#include

#include

intmain(){

inti=0;

structsockaddr_insaddr;

saddr.sin_addr.s_addr = inet_addr("127.0.0.1");

saddr.sin_port = htons(9988);

saddr.sin_family = AF_INET;

intaddlen = sizeof(saddr);

for(; i < 30; i++){

intsock=socket(AF_INET, SOCK_STREAM, 0);

connect(sock, (struct sockaddr *) &saddr, addlen);

write(sock, "Hello Server!", 13);

}

}

运行结果:

0818b9ca8b590ca3270a3433284dd417.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值