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重新编译没有帮助((