SOCKETSELECT(socketselect的设计方法)

http://www.itjxue.com  2023-02-22 10:10  来源:未知  点击次数: 

php socket_select怎么理解

PHP中 socket 的用法

首先的确认是否开启了socket

可以用phpinfo();查看是否开启了socket扩展,否则在php.ini中开启。

服务器端代码

例如:

?php

error_reporting(E_ALL);

set_time_limit(0);

//ob_implicit_flush();

$address = '127.0.0.1';

$port = 10005;

//创建端口

if( ($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) {

echo "socket_create() failed :reason:" . socket_strerror(socket_last_error()) . "\n";

}

//绑定

if (socket_bind($sock, $address, $port) === false) {

echo "socket_bind() failed :reason:" . socket_strerror(socket_last_error($sock)) . "\n";

}

//监听

if (socket_listen($sock, 5) === false) {

echo "socket_bind() failed :reason:" . socket_strerror(socket_last_error($sock)) . "\n";

}

do {

//得到一个链接

if (($msgsock = socket_accept($sock)) === false) {

echo "socket_accepty() failed :reason:".socket_strerror(socket_last_error($sock)) . "\n";

break;

}

//welcome 发送到客户端

$msg = "font color='red'server send:welcome/fontbr/";

socket_write($msgsock, $msg, strlen($msg));

echo 'read client message\n';

$buf = socket_read($msgsock, 8192);

$talkback = "received message:$buf\n";

echo $talkback;

if (false === socket_write($msgsock, $talkback, strlen($talkback))) {

echo "socket_write() failed reason:" . socket_strerror(socket_last_error($sock)) ."\n";

} else {

echo 'send success';

}

socket_close($msgsock);

} while(true);

//关闭socket

socket_close($sock);

?

服务器端需要在cli模式是执行,有可能cli模式下php.ini文件载入的不一样

可以像如下输出:

这时候在zhoxh目录下就有个tem.text文件。查看 Configuration File (php.ini) Path = C:\WINDOWS 。不是我的php.ini 文件,这说明调用的php.ini文件时错误的。这时候我们要指定php.ini文件命令如下

注意的是我的php可以直接执行时配置了环境变量。

客户端

例如:

?php

//error_reporting(E_ALL);

echo "h2tcp/ip connection /h2\n";

$service_port = 10005;

$address = '127.0.0.1';

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

if ($socket === false) {

echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";

} else {

echo "OK. \n";

}

echo "Attempting to connect to '$address' on port '$service_port'...";

$result = socket_connect($socket, $address, $service_port);

if($result === false) {

echo "socket_connect() failed.\nReason: ($result) " . socket_strerror(socket_last_error($socket)) . "\n";

} else {

echo "OK \n";

}

$in .= "HOST: localhost \r\n";

$in .= "Connection: close\r\n\r\n";

$out = "";

socket_write($socket, $in, strlen($in));

echo "OK\n";

echo "Reading response:\n\n";

while ($out = socket_read($socket, 8192)) {

echo $out;

}

echo "closeing socket..";

socket_close($socket);

echo "ok .\n\n";

?

c++ socket select怎么用

考虑用select系统调用吧,具体例子请自己找找 #include int select(int maxfdp1, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict exceptfds, struct timeval *restrict tvptr);

socket文件异常后select返回值

调用socket读写函数read(),write()时,都会有返回值。如果没有正确处理返回值,就可能引入一些问题

总结了以下几点

1当read()或者write()函数返回值大于0时,表示实际从缓冲区读取或者写入的字节数目

2当read()函数返回值为0时,表示对端已经关闭了 socket,这时候也要关闭这个socket,否则会导致socket泄露。netstat命令查看下,如果有closewait状态的socket,就是socket泄露了

当write()函数返回0时,表示当前写缓冲区已满,是正常情况,下次再来写就行了。

3当read()或者write()返回-1时,一般要判断errno

如果errno == EINTR,表示系统当前中断了,直接忽略

如果errno == EAGAIN或者EWOULDBLOCK,非阻塞socket直接忽略;如果是阻塞的socket,一般是读写操作超时了,还未返回。这个超时是指socket的SO_RCVTIMEO与SO_SNDTIMEO两个属性。所以在使用阻塞socket时,不要将超时时间设置的过小。不然返回了-1,你也不知道是socket连接是真的断开了,还是正常的网络抖动。一般情况下,阻塞的socket返回了-1,都需要关闭重新连接。

4.另外,对于非阻塞的connect,可能返回-1.这时需要判断errno,如果 errno == EINPROGRESS,表示正在处理中,否则表示连接出错了,需要关闭重连。之后使用select,检测到该socket的可写事件时,要判断getsockopt(c-fd, SOL_SOCKET, SO_ERROR, err, errlen),看socket是否出错了。如果err值为0,则表示connect成功;否则也应该关闭重连

5 在使用epoll时,有ET与LT两种模式。ET模式下,socket需要read或者write到返回-1为止。对于非阻塞的socket没有问题,但是如果是阻塞的socket,正如第三条中所说的,只有超时才会返回。所以在ET模式下千万不要使用阻塞的socket。那么LT模式为什么没问题呢?一般情况下,使用LT模式,我们只要调用一次read或者write函数,如果没有读完或者没有写完,下次再来就是了。由于已经返回了可读或者可写事件,所以可以保证调用一次read或者write会正常返回。

请教socket select 超时的可能原因

举例:

s=socket()();

设置s为non-blocking;

connect(s,..);

FD_SET...;

rc

=

select(...,

10s);

if

(rc

==

0)

表示10s超时了。

这个超时的意思是:10s之内,select中所有socket的事件均未产生(如果至少有一个产生,则rc大于0)

注意:这个10s跟connect本身的超时机制完全无关,前者的设置不影响后者。10s后select的返回,表明10s内connect还没成功,connect可能还在按自己的超时机制(例如慢启动)尝试重连(当然它最终也有个超时)。

至于connect本身的超时是否可以设置,可能各系统不一样。

顺便提醒:connect的socket必须是non-blocking类型,否则,connect会阻塞,也就没必要用select来检测是否连接成功。另外,那个s要注册到write类型的fd中,即select的第3个参数中。

其他listen,recv什么的,完全类似(但listen,recv本身没有什么超时概念)。只不过listen的和recv的socket,要注册到read的fd中。

socketselect一直能收到数据

我可以为您提供有关socketselect一直能收到数据的帮助。Socketselect是一种用于检测套接字是否可读、可写或有错误发生的函数,它可以让您检查多个套接字,并且只有当它们可读、可写或有错误发生时,才会返回。它可以帮助您确保您的程序一直能够收到数据,而不会因为网络延迟或其他原因而导致数据丢失。

(责任编辑:IT教学网)

更多

推荐Oracle文章