php搭建socket,php搭建环境
利用PHP如何实现Socket服务器
socket服务器的工作方式是这样的,不间断地运行以等待客户端的连接。一旦客户端连接上了,服务器就会将它添加到客户名单中,然后开始等待来自客户端的消息。
不要走开,下面是完整的源代码:
//?Set?time?limit?to?indefinite?execution??set_time_limit?(0);?????//?Set?the?ip?and?port?we?will?listen?on??$address?=?'localhost';??$port?=?10000;??$max_clients?=?10;?????//?Array?that?will?hold?client?information??$client?=?Array();?????//?Create?a?TCP?Stream?socket??$sock?=?socket_create(AF_INET,?SOCK_STREAM,?0);??//?Bind?the?socket?to?an?address/port??socket_bind($sock,?$address,?$port)?or?die('Could?not?bind?to?address');??//?Start?listening?for?connections??socket_listen($sock);?????echo?"Waiting?for?connections...\r\n";?????//?Loop?continuously??while?(true)?{??//?Setup?clients?listen?socket?for?reading??$read[0]?=?$sock;??for?($i?=?0;?$i??$max_clients;?$i++)?{???if?(isset($client[$i]['sock']))????$read[$i?+?1]?=?$client[$i]['sock'];??}??//?Set?up?a?blocking?call?to?socket_select()??if?(socket_select($read,?$write?=?NULL,?$except?=?NULL,?$tv_sec?=?5)??1)???continue;??/*?if?a?new?connection?is?being?made?add?it?to?the?client?array?*/?if?(in_array($sock,?$read))?{???for?($i?=?0;?$i??$max_clients;?$i++)?{????if?(empty($client[$i]['sock']))?{????$client[$i]['sock']?=?socket_accept($sock);????echo?"New?client?connected?$i\r\n";????break;????}????elseif?($i?==?$max_clients?-?1)????echo?"Too?many?clients...\r\n";???}??}?//?end?if?in_array?????//?If?a?client?is?trying?to?write?-?handle?it?now??for?($i?=?0;?$i??$max_clients;?$i++)?{?//?for?each?client???if?(isset($client[$i]['sock']))?{????if?(in_array($client[$i]['sock'],?$read))?{????$input?=?socket_read($client[$i]['sock'],?1024);????if?($input?==?null)?{?????echo?"Client?disconnecting?$i\r\n";?????//?Zero?length?string?meaning?disconnected?????unset($client[$i]);????}?else?{?????echo?"New?input?received?$i\r\n";?????//?send?it?to?the?other?clients?????for?($j?=?0;?$j??$max_clients;?$j++)?{?????if?(isset($client[$j]['sock'])??$j?!=?$i)?{??????echo?"Writing?'$input'?to?client?$j\r\n";??????socket_write($client[$j]['sock'],?$input,?strlen($input));?????}?????}?????if?($input?==?'exit')?{?????//?requested?disconnect?????socket_close($client[$i]['sock']);?????}????}????}?else?{????echo?"Client?disconnected?$i\r\n";????//?Close?the?socket????socket_close($client[$i]['sock']);????unset($client[$i]);????}???}??}??}?//?end?while??//?Close?the?master?sockets??socket_close($sock);
哎呀,乍一看这似乎是一个大工程,但是我们可以先将它分解为几个较小的部分。
第一部分是创建服务器。Lines:2至20。
这部分代码设置了变量、地址、端口、最大客户端和客户端数组。接下来创建socket并将其绑定到我们指定的地址和端口上。
下面我们要做的事情就是执行一个死循环(实际上我们是故意的!)。Lines:22至32。
在这部分代码中我们做的第一步是设置 $read 数组。此数
组包含所有客户端的套接字和我们主服务器的套接字。这个变量稍后会用于select语句:告诉PHP监听来自这些客户端的每一条消息。
socket_select()的最后一个参数告诉我们的服务器在返回值之前最多等待5秒钟。如果它的返回值小于1,那么就表示没有收到任何数据,所以只需要返回循环顶部,继续等待。
脚本的下一个部分,是增加新的客户端到数组中。Lines:33至44。
将新的客户端放置在列表的末尾。检查以确保客户端的数量没有超过我们想要服务器处理的数量。
下面要介绍的代码块相当大,也是服务器的主要部分。当客户端将消息发送到服务器时,就需要这块代码挺身而出来处理。消息可以是各种各样的,断开消息、实际断开——只要是服务器需要处理的消息。Lines:46至末尾。
代码循环通过每个客户端并检查是否收到来自于它们的消息。如果是,获取输入的内容。根据输入来检查这是否是一个断开消息,如果是那就从数组中删除它们,反之,那它就是一个正常的消息,那我们的服务器再次通过所有客户端,并一个一个写信息给他们,跳过发送者。
好了,下面试试创造你自己的聊天服务器吧!
PHP SOCKET 技术研究
今天试着写一个
PHP
与
C
语言通过socket通讯的程序,看过PHP手册,发现有好几种方式可以建立socket
客户端.
1、通过
fsockopen()
建立socket连接,然后用
用fputs()
发送消息,用
fgets()
接收消息。
2、通过
socket_create()
建立
socket
连接,然后用
socket_send()
or
socket_write()
发送消息,用
socket_recv()
or
socket_read()
发送消息。
很奇怪,我在手册上看到了这样一段话"本扩展模块是实验性的。该模块的行为,包括其函数的名称以及其它任何关于此模块的文档可能会在没有通知的情况下随
PHP
以后的发布而改变。我们提醒您在使用本扩展模块的同时自担风险。"
看来
php4.0
socket通讯还不是完全稳定。
今天我写的客户端要与服务端做两次通讯,我用上面这个方法都写了一个客户端程序,发现当仅仅就一次通讯的时候,也就是PHP客户端发送一次消息,然后接收返回消息,就关闭连接。这两种方法都能正确快速的实现功能,但当做两次通讯时,却有明显的差别,第一种方法第一次通讯特别快就结束了,这个我可以通过服务端的输出看出来,但是第二次通讯要等上好几分钟才能结束,我试了好几次都这样,我不太清楚我的程序哪里出错了,还是这个方式连接就是有问题,但是第二种方法做这两次通讯却很快,正确!完成的非常的。
最后我根据
第二种情况写了一个
class
//////////////////////////////
File
Description
//////////////////////////////////////////
//
Class
Name
:
socket
//
Version
:
V1.0
//
Functional
Outline
:
create
socket,and
send
message
to
server
//
Revision
history
:
2004/12/15
First
version
created
//
Current
:
2004/12/15
Liu
Yongsheng
//////////////////////////////////////////////////////////////////////////////////////////
class
socket{
var
$socket;
//socket
句柄
var
$sendflag
=
"";
var
$recvflag
=
"";
var
$response;
var
$debug
=
1;
function
socket($hostname,$port){
$address
=
gethostbyname($hostname);
$this-socket
=
socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
$result
=
socket_connect($this-socket,$address,$port);
if($this-debug
==
1){
if
($result
0)
{
echo
"socket_connect()
failed.\nReason:
($result)
"
.
socket_strerror($result)
.
"br";
}
else{
echo
"connect
OK.br";
}
}
}
function
sendmsg($msg){
socket_write($this-socket,$msg,strlen($msg));
$result
=
socket_read($this-socket,100);
$this-response
=
$result;
if($this-debug
==
1){
printf("font
color=#CCCCCC%s
$msg/fonbr",$this-sendflag);
printf("font
color=blue%s
$result/fontbr",$this-recvflag);
}
return
$result;
}
function
close(){
socket_close($this-socket);
}
}
如何用PHP实现Socket服务器
因为只有调用了accept客户端才能连上,你如果accept下面接一个循环,那么第二个用户不是说能不能进这个循环,而是连不进……此时只有第一个用户break出了循环,然后程序回头再调用accept,第二个用户才能连上。
用多进程来处理如何?因为accept一个客户端以后,应该是马上准备accept下一个客户端才对,而不是处理完现在这个客户端才accept下一个客户端。
socket_accept以后,直接调用 pcntl_fork(),此时进程会分裂为两个,其中一个的pnctl_fork返回值是0,另一个不是0。不是0的那个直接继续调用socket_accept即可,是0的那个处理客户端请求。
pnctl_fork不知道在windows下能不能用。
不过返回不是0的那个进程并不是这样就完事了,还要调用pcntl_wait防止子进程卡在那边没有完全结束。你可以在主进程里时不时就调用这个,配上WNOHANG作为option参数防止没有子进程需要wait的时候卡在那边。
这都是linux下常用的处理手段。说实话本来我想让你用多线程的,不过看了一圈不知道php里怎么用线程,倒是找到了用进程的方式,所以就