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

转自:http://blog.csdn.net/youjun9007228198/article/details/19946129     

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

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

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


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
           
           
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#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 ;
}
 来自CODE的代码片
serv.c

接下来我们来启动一下,查看结果如下:

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这个端口,并且产生竞争呢?我们来写一段客户端的代码做个测试。客户端主要是循环多次请求服务器,并发送字符串。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
           
           
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<netinet/in.h>
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 );
}
}
 来自CODE的代码片
clnt.c


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

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!

我们可以看出,这些进程都能监听同一个接口,而且还相互竞争,提高程序效率!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值