精华内容
下载资源
问答
  • 单个进程监听多个端口单个进程创建多个 socket 绑定不同的端口,TCP, UDP 都行多个进程监听同个端口(multiple processes listen on same port)方式1:通过 fork 创建子进程的方式可以实现,其他情况下不行。...

    单个进程监听多个端口

    单个进程创建多个 socket 绑定不同的端口,TCP, UDP 都行


    多个进程监听同一个端口(multiple processes listen on same port)

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

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

    NGINX 的 master/work 处理方法:

    Flow of an NGINX worker process

    可以设置 ffd 的 close-on-exec flag 避免子进程继承 fd.


    方式2:我们都知道socket是网络上两个进程之间的双向通信链路, 即

    socket = 《A进程的IP地址:端口号,B进程的IP地址:端口号》

    那么有个问题就很有意思了,不同的进程可以监听在同一个IP地址:端口号么?

    根据Unix网络编程中的知识可知,服务端监听一个端口会经历:

    1、根据套接字类型(Ipv4,Ipv6等)创建套接字socket

    2、将套接字bind绑定到具体的网络地址和端口号

    3、调用listen开始在这个套接字上进行监听。

    Unix提供了一个接口setsockopt()可以在bind之前设置套接字选项,其中就包括REUSEADDR这个选项,表明可以多个进程复用bind函数中指定的地址和端口号。

    由此可知多个应用(进程),包括同一个应用多次,都是可以绑定到同一个端口进行监听的。对应地C++、NET等高级语言也都提供了对应的接口。


    从一些例子也可以看出,比如有时候你在服务器上执行netstat -ano可能会发现同一个应用程序在同一个端口上有多个监听,这是因为一些服务端应用程序可能会异常退出或者没有完全释放套接字,但是需要在重新启动时还能够再次监听同一个端口,所以需要能够具备重复监听同一个端口的能力,因此也出现上述情形。


    展开全文
  • 一个进程控制多个socket

    千次阅读 2013-01-28 14:23:14
    本文用于验证,在erlang中 一个进程可以控制多个socket通信。验证程序如下: -module(test_tcp). -compile(export_all). -include_lib("kernel/include/inet.hrl"). -define(TCP_OPTIONS, [ binary, {packet, ...

    本文用于验证,在erlang中 一个进程可以控制多个socket通信。验证程序如下:

    -module(test_tcp).
    -compile(export_all).
    
    -include_lib("kernel/include/inet.hrl").
    
    -define(TCP_OPTIONS, [
    	binary, 
    	{packet, 0}, 
    	{active, once}, 
    	{exit_on_close, true}, 
    	{reuseaddr, true} ]).
    
    test() ->
    	Pid = spawn_link(?MODULE, loop, []),
    	{ok, Listen} = gen_tcp:listen(6099, ?TCP_OPTIONS),
    	loop_listen(Listen, Pid).
    
    loop_listen(Listen, Pid) ->
    	{ok, Sock} = gen_tcp:accept(Listen),
    	gen_tcp:controlling_process(Sock, Pid),
    	loop_listen(Listen, Pid).
    
    loop() ->
    	receive 
    		{tcp, Sock, Bin} ->
    			io:format("rcv from ~p: ~p", [Sock, Bin]),
    			inet:setopts(Sock, [{active, once}]),
    			loop()
    	end.


    启动本脚本;外界可以连接6099端口,发送数据。可以看到,不同的连接发送的数据,被同一个控制进程捕获到。



    展开全文
  • 如何多个进程监听同一个端口

    千次阅读 2020-06-03 11:13:52
    有哪些方法可以实现多个进程监听同一个端口呢? 2. 方案:fork 只要在绑定端口号(bind函数)之后,监听端口号之前(listen函数),用fork()函数生成子进程,这样子进程就可以克隆父进程,达到监听同一个端口...

    1. 问题描述

    一个进程监听端口,经验告诉我们,如果多次启动一个进程会报错:“Address already in use!"。这是由于bind函数导致的,由于该端口号已经被第一个进程监听了。有哪些方法可以实现多个进程监听同一个端口呢?

    2. 方案一:fork

    只要在绑定端口号(bind函数)之后,监听端口号之前(listen函数),用fork()函数生成子进程,这样子进程就可以克隆父进程,达到监听同一个端口的目的,而且还相互竞争,提高程序效率。

    这里要注意的是,TCP三次握手创建连接是不需要服务进程参数的,而服务进程仅仅要做的事调用accept将已建立的连接构建对应的连接套接字connfd

    bind()

    fork()

    listen()

    2.1 惊群现象

    多个服务进程同时阻塞在accept等待监听套接字已建立连接的信息,那么当内核在该监听套接字上建立一个连接,那么将同时唤起这些处于accept阻塞的服务进程,从而导致“惊群现象”的产生,唤起多余的进程间影响服务器的性能(仅有一个服务进程accept成功,其他进程被唤起后没抢到“连接”而再次进入休眠)。

    2.2 惊群问题

    惊群会导致资源竞争,对于操作系统来说,多个进程/线程在等待同一资源时,也会产生类似的效果,其结果就是每当资源可用,所有的进程/线程都来竞争资源,会造成以下后果:

    • 系统对用户进程/线程频繁的做无效的调度、上下文切换,系统性能大打折扣。
    • 为了确保只有一个线程得到资源,用户必须对资源操作进行加锁保护,进一步加大了系统开销。

    2.3 惊群解决

    2.3.1 方法一

    在Linux 2.6版本之前,监听同一个socket的进程会挂在一个等待队列上,当请求到来时,会唤醒所有等待的子进程。
    当时可以使用锁解决这种惊群问题。

    for(;;) {
        lock();
        int client = accept(...);
        unlock();
        if (client < 0) continue;
        ...
    }

    2.3.2 方法二

    在Linux 2.6版本之后,通过引入一个标记位,解决掉了惊群问题。内核开发者增加了一个“互斥等待”选项。一个互斥等待的行为与睡眠基本类似,主要的不同点在于:
    1)当一个进程加入等待队列时,如果该进程有 WQ_FLAG_EXCLUSEVE 标志置位,它被添加到等待队列的尾部。没有这个标志,则添加到队列开始。
    2)当 wake_up 在一个等待队列上被调用时,它会唤醒第一个有 WQ_FLAG_EXCLUSIVE 标志的进程后停止。
    也就是说,对于互斥等待的行为,比如对一个Socket,多线程阻塞accept时,系统内核只会唤醒所有正在等待此事件的队列的第一个,队列中的其他进程则继续等待下一次事件的发生,这样就避免的多个线程同时监听同一个socket时的惊群问题。

    3. 方案二:SO_REUSEPORT

    SO_REUSEPORT支持多个进程或者线程绑定到同一端口,提高服务器程序的性能

    • 允许多个套接字 bind()/listen() 同一个TCP/UDP端口
      • 每一个线程拥有自己的服务器套接字
      • 在服务器套接字上没有了锁的竞争
    • 内核层面实现负载均衡
    • 安全层面,监听同一个端口的套接字只能位于同一个用户下面

    其核心的实现主要有三点:

    • 扩展 socket option,增加 SO_REUSEPORT 选项,用来设置 reuseport。
    • 修改 bind 系统调用实现,以便支持可以绑定到相同的 IP 和端口
    • 修改处理新建连接的实现,查找 listener 的时候,能够支持在监听相同 IP 和端口的多个 sock 之间均衡选择。

    有了SO_RESUEPORT后,每个进程可以自己创建socket、bind、listen、accept相同的地址和端口,各自是独立平等的。让多进程监听同一个端口,各个进程中accept socket fd不一样,有新连接建立时,内核只会唤醒一个进程来accept,并且保证唤醒的均衡性。

     

    参考

    https://www.jianshu.com/p/1cdd61a6e3ea

    展开全文
  • 单个进程能否监听多个端口? 当然随着学习的深入,答案均是肯定的,在这个过程中笔者为了验证,用php写了两个例子,在这里分享出来,供有需要的php同学学习跟理解。 在分享例子之前,需要先介绍两个php在socket...

    转自:http://www.jianshu.com/p/f440c19e77ac

    最近在看nginx设计原理时思考到两个问题,便是:

    • 多个进程能否监听同个端口?
    • 单个进程能否监听多个端口?

    当然随着学习的深入,答案均是肯定的,在这个过程中笔者为了验证,用php写了两个例子,在这里分享出来,供有需要的php同学学习跟理解。

    在分享例子之前,需要先介绍两个php在socket编程中常用的扩展,pcntl和libevent:

    1. pcntl

    php本身并不支持多进程,但通过扩展pcntl便可以实现fork功能,fork编程的大概原理是,每次调用fork函数,操作系统就会产生一个子进程,儿子进程所有的堆栈信息都是原封不动复制父进程的,而在fork之后,父进程与子进程实际上是相互独立的,父子进程不会相互影响。也就是说,fork调用位置之前的所有变量,父进程和子进程是一样的,但fork之后则取决于各自的动作,且数据也是独立的;因为数据已经完整的复制给了子进程。而唯一能够区分父子进程的方法就是判断fork的返回值。如果为0,表示是子进程,如果为正数,表示为父进程,且该正数为子进程的PID(进程号),而如果是-1,表示子进程创建失败。

    2. libevent

    linux网络编程中有三大事件处理,IO(socket)、信号和定时器,理解并处理好这三者,linux网络编程就理解了一半,而libevent则是对这三者处理提供了一个很好的封装,大大简化了socket编程中事件处理的难度,非常推荐对这块感兴趣的同学去深入学习。

    一、多个进程监听同个端口

    <?php
    
    /**
    * 
    */
    class Server
    {
        protected $ip = '127.0.0.1';
        protected $port = 5000;
        protected $sock = null;
    
        public function main()
        {
            if(($this->sock = socket_create(AF_INET,SOCK_STREAM,SOL_TCP)) < 0) {
                echo "socket_create() 失败的原因是:".socket_strerror($sock)."\n";
                return ;
            }
    
            if(($ret = socket_bind($this->sock,$this->ip,$this->port)) < 0) {
                echo "socket_bind() 失败的原因是:".socket_strerror($ret)."\n";
                return ;
            }
    
            if(($ret = socket_listen($this->sock,4)) < 0) {
                echo "socket_listen() 失败的原因是:".socket_strerror($ret)."\n";
                return ;
            }
    
            for ($i=0; $i<3; $i++)
            {
                $pid = pcntl_fork();
                if (-1 === $pid) {
                    throw new Exception("fork fail");
                } elseif (0 === $pid) {
                    echo "fork pid:".getmypid()."\n";
                    while (1) {
                        if(($msgsock = socket_accept($this->sock)) < 0) {
                            echo "socket_accept() failed: reason: " . socket_strerror($msgsock) . " ,pid: ".getmypid()."\n";
                            break;
                        }else{
                            $msg ="测试成功 ! \n";
                            echo $msg."pid: ".getmypid()."\n";
                            socket_write($msgsock, $msg, strlen($msg));
                        }
                    }
                }    
            }
            while(1)
            {
                $status = 0;
                $pid = pcntl_wait($status,WUNTRACED);    
                if($pid > 0)
                {
                    echo "pid:$pid exit,status:$status";
                }        
            }
    
        }
    
    }
    
    $server = new Server();
    $server->main();

    二、单个进程监听多个端口

    <?php
    
    /**
    * 
    */
    class Server
    {
        protected $socks = array();
        protected $event_base = null;
        protected $events = array();
        public function __construct()
        {
            $this->event_base = event_base_new();
        }
    
        protected function acceptConnect($sock)
        {
            echo "acceptConnect pid:".getmypid()."\n";
            //sleep(5);
            if(($msgsock = socket_accept($sock)) < 0) {
                echo "socket_accept() failed: reason: " . socket_strerror($msgsock) . " ,pid: ".getmypid()."\n";
                //break;
            }else{
                $msg ="测试成功,sock:$sock ! \n";
                echo $msg."pid: ".getmypid()."\n";
                socket_write($msgsock, $msg, strlen($msg));
                socket_close($msgsock);
            }
        }
    
        protected function addEvent($sock,$callback)
        {
            $event = event_new();
    
            if (!event_set($event, $sock, EV_READ|EV_PERSIST, $callback, null)) {
                echo "event_set faild,pid:".getmypid()."\n";
                return ;
            }
    
             if (!event_base_set($event,$this->event_base)) {
                echo "event_base_set faild,pid:".getmypid()."\n";
                return ;
            }
    
            if (!event_add($event)) {
                echo "event_add faild,pid:".getmypid()."\n";
                return ;
            }
    
            $this->event[] = $event;
        }
    
        public function listen($ip = '127.0.0.1',$port = '5000')
        {
            if(($sock = socket_create(AF_INET,SOCK_STREAM,SOL_TCP)) < 0) {
                echo "socket_create() 失败的原因是:".socket_strerror($sock)."\n";
                return ;
            }
    
            if(($ret = socket_bind($sock,$ip,$port)) < 0) {
                echo "socket_bind() 失败的原因是:".socket_strerror($ret)."\n";
                return ;
            }
    
            if(($ret = socket_listen($sock,4)) < 0) {
                echo "socket_listen() 失败的原因是:".socket_strerror($ret)."\n";
                return ;
            }
    
            $this->socks[] = $sock;
        }
    
        public function main()
        {
            if($this->event_base == null)
            {
                echo "event base null";
                return ;
            }
            echo "event base:".$this->event_base."\n";
            foreach ($this->socks as $sock) {
                echo "sock:$sock\n";
                $this->addEvent($sock,array($this,'acceptConnect'));
            }
            echo "libevent success,pid:".getmypid()."\n";
            $result = event_base_loop($this->event_base);        
            echo "event loop result:$result";
        }
    
    }
    
    $server = new Server();
    $server->listen('127.0.0.1','5000');
    $server->listen('127.0.0.1','5001');
    $server->main();

    展开全文
  • 网络--多个进程能否监听同一端口

    千次阅读 2018-04-16 09:15:33
    文章出自jiq•钦’s technical Blog - 季义...那么有个问题就很有意思了,不同的进程可以监听在同一个IP地址:端口号么? 根据Unix网络编程中的知识可知,服务端监听一个端口会经历: 1、根据套接字类型(Ipv4,Ipv6...
  • 一直疑惑同一个应用app如何才能以多进程线程的方式运行。对于线程可能很好理解,我们只要在进程中启用线程的模式即可。也就是来一个请求,我们就用函数pthread_create()启用一个线程即可。这样我们的应用...
  • 网络-一个进程是否能拥有多个端口

    千次阅读 2019-03-05 09:26:36
    1.端口理解 其它网友的观点 ... 博文中打的比喻个人觉得很形象,特此引用一下。...其它网友也有相同的问题,大部分人认为一个进程可以拥有多个端口。 端口 下面是引用别人博客的话,同样觉得挺形象。socke...
  • 多个socket绑定同一个端口,叫做端口复用 下列代码可以使用socket绑定多次 多个socket绑定同一个端口,叫做端口复用 下列代码可以使用socket绑定多次 //SO_REUSEADDR选项就是可以实现端口重绑定的  if...
  • tomcat作为服务端程序,一直在监听80端口,之前一直以为tomcat每接收到一个新的连接,都会创建一个新的socket,然后这个socket又会占用一个端口。但是事实上并不是这样的,肯定是会创建新的socket的,但是这个新创建...
  • 多个进程能否监听同一个端口

    千次阅读 2019-05-31 14:03:17
    那么有个问题就很有意思了,不同的进程可以监听在同一个IP地址:端口号么?根据Unix网络编程中的知识可知,服务端监听一个端口会经历:1、根据套接字类型(Ipv4,Ipv6等)创建套接字socket2、将套接字bind绑定到具体的...
  • 个端口可以有多个socket,但其中只能有一个处于listen状态。这就是accept后可以用oldsock监听同时用newsock通信的基础2.监听socket监听的是指定端口,一旦accept了新的socket,那么新socket使用另一个自由端口...
  • 多个socket使用同一端口

    万次阅读 2014-02-22 10:33:42
    突然想到多个socket能不能绑定同一个端口?度娘不给力,自己做实验,结论如下: 1. 如果设置SO_REUSEADDR,就是端口复用,只有一个socket能收到,毕竟只有一块肉嘛,给那个socket,另一个必然要饿肚子,除非有copy...
  • Socket端口复用 ...一个监听(listen)server已经启动  2.当有client有连接请求的时候,server产生一个子进程去处理该client的事物. 3.server主进程终止了,但是子进程还在占用该连接处理client的事情.虽然子进
  • 多个进程能否监听同一个端口号?

    万次阅读 2016-03-22 22:58:55
     那么有个问题就很有意思了,不同的进程可以监听在同一个IP地址:端口号么?根据Unix网络编程中的知识可知,服务端监听一个端口会经历:1、根据套接字类型(Ipv4,Ipv6等)创建套接字socket2、将套接字bind绑定到具体的...
  • 单个进程监听多个端口 单个进程创建多个 socket 绑定不同的端口,TCP, UDP 都行   方式1:通过 fork 创建子进程的方式可以实现,其他情况下不行。 当连接到来时,子进程、父进程都可以 accept, 这就是著名的...
  • 使用netty框架,怎么在一个进程内监听多个端口 当监听一个端口后,监听会进入阻塞,那另一个端口就没法监听了。 示例程序如下 EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup ...
  • 多个进程可以监听同一个端口?

    千次阅读 2012-06-27 16:17:22
    多个socket绑定同一个端口,叫做端口复用 下列代码可以使用socket绑定多次 //SO_REUSEADDR选项就是可以实现端口重绑定的  if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val))!=0)  {  ...
  • 测试目标:建立多个socket的测试 测试环境:suse Linux 测试步骤:建立了3个socket,但是由于绑定了不同的端口,可以邦定成功;假如绑定相同的端口,则相继失败。而关闭socket的时候,调用shutdown失败,而close却...
  • void ReceiveTest() { //1 创建套节字 System.Net.Sockets.Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); s.SetSocketOp
  • 最近在linux下弄一些socket方面的东西,涉及到父子进程、兄弟进程间的端口socket句柄的问题,主要问题集中在两方面: 1、假如父进程监听A端口,那么在client端来连接,并fork子进程,那么子进程通过...
  • 一、在前面讲过的最简单的回射客户/服务器程序中,一个客户端即一个进程,只会发起一个连接,只要稍微修改一下就可以让一个客户端发起多个连接,然后只利用其中一个连接发送数据。 先来认识一个函数getsockname  #...
  • 阅读目录 一:nodejs进程进化及多进程架构原理 ...NodeJS是基于chrome浏览器的V8引擎构建的,它是单线程单进程模式,nodeJS的单线程指js的引擎只有一个实列。且是在主线程执行的,这样的优点是:可以减少线程间切换...
  • accept是又产生一个Socket端口吗?

    千次阅读 2010-03-10 14:57:00
    accept是又产生一个Socket端口吗? 要写网络程序就必须用Socket,这是程序员都知道的。而且,面试的时候,我们也会问对方会不会Socket编程?一般来说,很多人都会说,Socket编程基本就是listen,accept以及send,...
  • java 进程socket获取空闲端口

    千次阅读 2012-06-30 13:57:46
    1 、获取当前进程ID   public static long getPID() {  String processName =  java.lang.management.ManagementFactory.getRuntimeMXBean().getName();  return Long.parseLong(processName.split("@")
  • 线程情况下,服务器端监听(listen)某个端口后,每accept一个客户端的连接就会产生一个新的Socket 新产生的Socket端口是多少?  答案是服务器端口还是Listen端口。  进程间不能用同一端口,但是进程...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 133,162
精华内容 53,264
关键字:

一个进程多个端口socket