zz``unix/linux 系统实现多个进程监听同一个端口

https://blog.csdn.net/youjun9007228198/article/details/19946129

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

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

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

 

#include
#include
#include
#include
#include
#include

#define oops(m) {perror(m); exit(1);}
int main(){
int sock_id;
struct sockaddr_in saddr;
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”
int i;
for(i = 0; i < 6; i++){//连续创建六个子进程
int pid = fork();
if(pid == 0) break;
}
listen(sock_id, 1);
while(1){
int sock = accept(sock_id, NULL, 0);
char buf[128];
int readnum;
readnum = read(sock, buf, 127);
buf[readnum] = '\0';
printf("pid=%d, mesg: %s\n", getpid(), buf);
fflush(stdout);
close(sock);
}
return 1;
}
接下来我们来启动一下,查看结果如下:

F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S   500  3019  2370  0  80   0 -  1315 -      tty2     00:00:01 bash
0 S   500  7332  3019  0  80   0 -   466 -      tty2     00:00:00 multi_proc
1 S   500  7333  7332  0  80   0 -   466 -      tty2     00:00:00 multi_proc
1 S   500  7334  7332  0  80   0 -   466 -      tty2     00:00:00 multi_proc
1 S   500  7335  7332  0  80   0 -   466 -      tty2     00:00:00 multi_proc
1 S   500  7336  7332  0  80   0 -   466 -      tty2     00:00:00 multi_proc
1 S   500  7337  7332  0  80   0 -   466 -      tty2     00:00:00 multi_proc
1 S   500  7338  7332  0  80   0 -   466 -      tty2     00:00:00 multi_proc

 

我们可以看到,确实有多个服务(multi_proc)成功起来了,那么这些进程是否能够监听9988这个端口,并且产生竞争呢?我们来写一段客户端的代码做个测试。客户端主要是循环多次请求服务器,并发送字符串。

#include
#include
#include
#include
#include
#include

int main(){
int i=0;
struct sockaddr_in saddr;
saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
saddr.sin_port = htons(9988);
saddr.sin_family = AF_INET;
int addlen = sizeof(saddr);
for(; i < 30; i++){
int sock=socket(AF_INET, SOCK_STREAM, 0);
connect(sock, (struct sockaddr *) &saddr, addlen);
write(sock, "Hello Server!", 13);
}
}


请求执行后,我们看一下,服务器打印的结果!

pid=7738, mesg: Hello Server!

pid=7736, mesg: Hello Server!

pid=7735, mesg: Hello Server!

pid=7734, mesg: Hello Server!

pid=7733, mesg: Hello Server!

pid=7733, mesg: Hello Server!

pid=7737, mesg: Hello Server!

pid=7737, mesg: Hello Server!

pid=7736, mesg: Hello Server!

pid=7735, mesg: Hello Server!

pid=7734, mesg: Hello Server!

pid=7732, mesg: Hello Server!

pid=7733, mesg: Hello Server!

pid=7738, mesg: Hello Server!

pid=7737, mesg: Hello Server!

pid=7736, mesg: Hello Server!

pid=7735, mesg: Hello Server!

pid=7734, mesg: Hello Server!

pid=7732, mesg: Hello Server!

pid=7733, mesg: Hello Server!

pid=7738, mesg: Hello Server!

pid=7737, mesg: Hello Server!

pid=7736, mesg: Hello Server!

pid=7735, mesg: Hello Server!

pid=7734, mesg: Hello Server!

pid=7732, mesg: Hello Server!

pid=7733, mesg: Hello Server!

pid=7738, mesg: Hello Server!

pid=7737, mesg: Hello Server!

pid=7738, mesg: Hello Server!

我们可以看出,这些进程都能监听同一个接口,而且还相互竞争,提高程序效率!
————————————————
版权声明:本文为CSDN博主「http协议」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/youjun9007228198/article/details/19946129


 

posted on 2019-09-24 11:00  小豆角  阅读(410)  评论(0编辑  收藏  举报

导航