PHP:TCP 套接字,“无法绑定地址”

Posted

技术标签:

【中文标题】PHP:TCP 套接字,“无法绑定地址”【英文标题】:PHP: TCP sockets, 'unable to bind address' 【发布时间】:2015-12-25 16:24:02 【问题描述】:

我见过其他人有这个问题,但也许我可以解释一下我的情况,你可以指出问题可能出在哪里。

我收到“警告:socket_bind():无法绑定地址 [98]:地址已在使用中”错误。

情况是这样的。我正在使用 Web 应用程序来触发另一个程序来执行任务(从网页界面)。该程序的结果通过套接字发送到我正在侦听套接字的 Web 应用程序。

首先我创建并打开套接字,然后我触发另一个程序,然后当该程序完成时,它应该通过套接字将其结果发送回。

第一次尝试效果很好。然后下一次尝试(我多次触发这个过程)我在尝试打开套接字时得到上述套接字绑定错误,显然套接字仍然被绑定。

我等待大约一分钟,我可以再次成功运行该过程。我认为套接字连接超时。

我不知道问题是因为我构建套接字代码的方式,还是问题出在我正在触发的外部程序中。我不太了解外部程序的内部结构,因为它是由其他人构建的 jar 文件。

这是我用于创建和处理套接字的代码。我只是在 php.net 上使用了一个示例,并根据我的需要对其进行了更改。

    $port1 = 15000;        


    // configure the socket
    error_reporting(E_ALL);
    set_time_limit(0);
    ob_implicit_flush();            
    $address = '127.0.0.1';
    $port2 = 54321;
    $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    $error = 'none';

    if ($sock) 

        if (socket_bind($sock, $address, $port2)) 

            if (socket_listen($sock, 5))  

                // trigger external process 
                if (start_calibration())                         

                    $buf = array();

                    // listen to the socket for incoming messages
                    do 
                        // if incomming connection is not accepted break out and close socket
                        if (($msgsock = socket_accept($sock)) === false) 
                            break;
                        

                        do 
                            // if cant read socket then break out and close socket
                            if (false === ($buf = socket_read($msgsock, 2048, PHP_BINARY_READ))) 
                                break 2;
                            

                            $buf = unpack('C*', $buf);

                            socket_close($msgsock);
                            break 2;
                         while (true);
                        socket_close($msgsock);
                     while (true);

                    socket_close($sock);

                    // code to handle data recieved through the socket

                      
                else 
                    // start_calibration failed
                    $error = 'start_calibration failed';
                    socket_close($sock);
                                        
            
            else 
                // socket_listen failed
                $error = 'socket_listen failed';
                socket_close($sock);
                                
        
        else 
            // socket_bind failed
            $error = 'socket_bind failed';
            socket_close($sock);
                        
    
    else 
        // socket_create failed
        $error = 'socket_create failed';
    

    $data['error'] = $error;
    echo json_encode($data);

另外,如果“socket_bind”、“socket_listen”等行出现问题,是否有更有效的方法来处理套接字的关闭?

【问题讨论】:

这是一个 CLI 脚本吗?如果是,请运行一次,然后它就是一个侦听端口的小型服务器。如果您的操作系统内核支持同时侦听同一端口的多个进程,您可以尝试重用地址。但是,整个事物的架构似乎有些不对劲。 【参考方案1】:

您是否尝试在您的套接字上设置标志SO_REUSEADDR? 在socket_set_option 的documentation 中有一个示例。

【讨论】:

以上是关于PHP:TCP 套接字,“无法绑定地址”的主要内容,如果未能解决你的问题,请参考以下文章

socket_bind():无法绑定地址 [99](Amazon EC2 上的 Ubuntu)

socket_bind() 无法绑定地址

PHP反复从TCP套接字接收数据

通过 Unix 套接字和 TCP/IP 套接字运行 PHP-FPM 有啥区别?

如何使用 HTTP Pipelining 通过单个 TCP 套接字发送 PHP cURL 句柄?

PHP TCP 套接字连接限制 - Windows 服务器