0

php版本:

PHP 7.2.2 (cli) (built: Dec 16 2019 23:27:31) ( ZTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies

os 是 ubuntu 服务器版本 18.04。

我用php cmd试过了。

服务器代码,输出为“BEFORE CONNECT”:

$address="127.0.0.1";
$port="3222";
$sock=socket_create(AF_INET,SOCK_STREAM,0) or die("Cannot create a socket");
socket_bind($sock,$address,$port) or die("Couldnot bind to socket");
socket_listen($sock) or die("Couldnot listen to socket");

var_dump('BEFORE ACCEPT');
$accept=socket_accept($sock) or die("Couldnot accept");
$read=socket_read($accept,1024) or die("Cannot read from socket");
echo $read;
socket_write($accept,"Hello client");
socket_close($sock);

客户端代码:

$address="127.0.0.1";
$port="3222";
$msg="Hello server";

$sock=socket_create(AF_INET,SOCK_STREAM,0) or die("Cannot create a socket");

var_dump('BEFORE CONNECT');
socket_connect($sock,$address,$port) or die("Could not connect to the socket");
socket_write($sock,$msg);

$read=socket_read($sock,1024);
echo $read;
socket_close($sock);

问题是客户端脚本与 socket_connect() 函数一起挂起,一段时间后我得到:

Warning: socket_connect(): unable to connect [110]: Connection timed out in "script"

但是在我本地的 Ubuntu 18.04.3 LTS 上它可以工作。PHP 也是一样。

我还尝试在外部 ip 上创建服务器并从外部访问它,结果相同 - 它挂起。但是,如果我在客户端将端口更改为错误 - 我会立即收到警告:Warning: socket_connect(): unable to connect [111]: Connection refused in

ubuntu 中添加了以下配置:

/etc/sysctl.conf file:


net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.tcp_max_orphans = 65536
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_keepalive_time = 1800
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.tcp_synack_retries = 1
net.ipv4.tcp_mem = 50576   64768   98152
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_orphan_retries = 0
net.ipv4.tcp_syncookies = 0
net.ipv4.netfilter.ip_conntrack_max = 16777216
net.netfilter.nf_conntrack_max = 16777216
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_congestion_control = htcp
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.route.flush = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.lo.rp_filter = 1
net.ipv4.conf.eth0.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.lo.accept_source_route = 0
net.ipv4.conf.eth0.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_rfc1337 = 1
net.ipv4.ip_forward = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_echo_ignore_all = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 1000
net.core.rmem_default = 65536
net.core.wmem_default = 65536
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
fs.inotify.max_user_watches = 16777216

和:

sysctl -w fs.file-max=12000500
sysctl -w fs.nr_open=20000500
# Set the maximum number of open file descriptors for current shell session
ulimit -n 20000000

/etc/security/limits.conf
# <domain> <type> <item>  <value>
*       soft  nofile  20000
*       hard  nofile  20000

# Set the memory size for TCP with minimum, default and maximum thresholds 
sysctl -w net.ipv4.tcp_mem='10000000 10000000 10000000'

# Set the receive buffer for each TCP connection with minumum, default and maximum thresholds
sysctl -w net.ipv4.tcp_rmem='1024 4096 16384'

# Set the TCP send buffer space with minumum, default and maximum thresholds 
sysctl -w net.ipv4.tcp_wmem='1024 4096 16384'

# The maximum socket receive buffer sizemem_max=16384
sysctl -w net.core.rmem_max=16384

# The maximum socket send buffer size
sysctl -w net.core.wmem_max=16384

其中一些配置是否有可能使 socket_connect 挂起?

啊,防火墙状态是inactive,检查sudo ufw status

相同的代码适用于其他 2 个具有相同 PHP 编译的相同 ubuntu 安装。

顺便说一句,mysql 和 apache2 在那台机器上运行良好。

看起来服务器脚本不接受连接,我的意思是这段代码socket_accept($sock),因为我尝试连接客户端 php 脚本,尝试连接 telnet,并且我尝试在外部 IP 上创建服务器,当我尝试连接它时从我的另一台计算机 - 同样的情况,socket_connect 挂起。好像服务器不接受连接..

我还尝试了非阻塞模式的 php 套接字服务器:

$address="127.0.0.1";
$port="3222";
$sock=socket_create(AF_INET,SOCK_STREAM,0) or die("Cannot create a socket");
socket_bind($sock,$address,$port) or die("Couldnot bind to socket");
socket_listen($sock) or die("Couldnot listen to socket");

socket_set_nonblock($sock);

var_dump('BEFORE ACCEPT');

while (1) {
    if($accept=socket_accept($sock)) {
        $read=socket_read($accept,1024) or die("Cannot read from socket");
        echo $read;
        socket_write($accept,"Hello client");
        socket_close($sock);
        die;
    }
    sleep(1);
}

因此服务器每 1 秒尝试接受一次连接。但还是一样的结果((

这很疯狂,因为如果我按以下方式创建服务器,它可以工作:

$address="127.0.0.1";
$port="3222";
$socket = stream_socket_server("tcp://{$address}:{$port}", $errno, $errstr);
if (!$socket) {
    echo "$errstr ($errno)<br />\n";
} else {
    while ($conn = stream_socket_accept($socket)) {
        fwrite($conn, 'Локальное время ' . date('n/j/Y g:i a') . "\n");
        fclose($conn);
    }
    fclose($socket);
}

还有一点,类比 Python 脚本运行良好!

Python服务器:

#!/usr/bin/env python3

import socket

HOST = '127.0.0.1'  # Standard loopback interface address (localhost)
PORT = 33        # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print('Connected by', addr)
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)

Python客户端:

#!/usr/bin/env python3

import socket

HOST = '127.0.0.1'  # The server's hostname or IP address
PORT = 33        # The port used by the server

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))
    s.sendall(b'Hello, world')
    data = s.recv(1024)

print('Received', repr(data))

但为什么 PHP 不起作用?可能是什么问题?

PHP重新编译没有帮助((

4

0 回答 0