这是我的代码:
<?php
$host = "127.0.0.1";
$portListen = 1234;
$portSend = 1240;
// create socket
$sSender = socket_create(AF_INET, SOCK_STREAM, 0);
socket_connect($sSender, $host, $portListen);
socket_write($sSender, "test", strlen ("test"));
$sListen = socket_create(AF_INET, SOCK_STREAM, 0);
socket_set_option($sListen, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($sListen, $host, $portSend);
socket_listen($sListen,1);
$dataSock = socket_accept($sListen);
echo socket_read($dataSock, 3, PHP_NORMAL_READ);
// close sockets
socket_close($sSender);
socket_close($sListen);
?>
我将“test”发送到另一个应用程序,它接收并发回“ack”。问题是,我只能这样做一次。如果我刷新,我得到的地址已经使用错误。我尝试了在php.net上建议的解决方案,但无济于事。尝试在socket_close()之前使用socket_shutdown()只会给我一些未连接的警告,并且在刷新时会给我一个永无止境的加载。
根据我的理解,套接字没有立即关闭的原因是因为缓冲区中仍有数据。但是你可以看到我明确表示只听一个连接。另外,我只从我的应用程序中发送3个字符,并在此脚本中读取3个字符。
我做错了什么?
编辑:我使用2个套接字的原因是因为我在write()之后无法监听(),这给了我套接字已经连接错误。在write()之后跳过listen()并直接读取read()会给我带来无效的参数错误。
答案 0 :(得分:2)
我看到,经过几个小时的睡眠并重新分析我的代码和文档后,我设法解决了所有问题。你们是对的,1个插槽确实足够和正确的方式:
<?php
$host = "127.0.0.1";
$portListen = 1234;
$sSender = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n");
socket_connect($sSender, $host, $portListen) or die("Could not connect\n");
socket_write($sSender, "test", strlen ("test")) or die("Could not write output\n");
echo socket_read($sSender, 3, PHP_NORMAL_READ);
socket_close($sSender);
?>
这么简单!
答案 1 :(得分:1)
为什么需要创建2个用于读写的套接字?它看起来像一个奇怪的设计。客户端应用程序通常打开与服务器的套接字连接,然后发送请求并在同一套接字上读取服务器的响应。 此外,创建侦听套接字(低于服务器)将无法扩展到任何防火墙或NAT网关。
回答你的评论:不需要听。只是阅读(如果您的服务器尚未回复,可能会阻止操作)。
答案 2 :(得分:1)
连接关闭后,套接字进入延迟状态,以便在(关闭期间)数据包丢失并重新传输时,响应将是一个干净的确认,而不是RST
(重置),表示没有这样的套接字是公开的。它是TCP规范的一部分,你不能让它停止发生。
Listen(1)
并不意味着只接受一个连接,它意味着维护一个连接的队列,等待一个应用程序accept()
。因此,只要您接受第一个,套接字就可以收听更多内容了。
和其他人一样,我想知道为什么奇怪的设计,但我认为这是一个简单的例子,它提出了你的问题,并不一定能提出你的真实计划。