php socket编程视频,php实现socket网络编程

之前本人其实写过一个tcp多进程服务器了http://www.php20.cn/article/139,本文将总结以及完善php实现网络服务器相关代码

php实现tcp服务器

tcp服务器的实现,其实和c语言实现的步骤差不多,大概为:

创建一个socket

绑定socket为tcp,到网卡中

监听socket(将socket改为可接受其他进程的请求)

阻塞/非阻塞,循环获取连接事件<?php

$listen_host = '0.0.0.0';

$port = '8080';

$tcp_socket = socket_create(AF_INET/*ipv4*/,SOCK_STREAM/*tcp类型*/,SOL_TCP/*tcp*/);

if ($tcp_socket===false){

die("socket_create() fail:" . socket_strerror(socket_last_error()) . "/n");

}

socket_bind($tcp_socket,$listen_host ,$port)||die('bind error');//绑定

socket_listen($tcp_socket)||die('listen error');//监听

socket_set_nonblock($tcp_socket);//设置非阻塞

socket_set_option($tcp_socket,SOL_SOCKET,SO_REUSEADDR,1);//SO_REUSEADDR 可避免程序意外退出,导致端口绑定失败

$client_arr = [];

while(1){

$connection = socket_accept($tcp_socket);

if($connection){//如果有新链接,则处理新链接

echo $connection."连接成功\n";

$client_arr[$connection] = $connection;

socket_set_nonblock($connection);//设置客户端非阻塞

}

//处理客户端

foreach ($client_arr as $client){

$data='';

$result = @socket_recv($client,$data, 1024,MSG_DONTWAIT);

if($result===false){//出错

$error_id = socket_last_error();

if($error_id!==11){

socket_clear_error();

throw new Exception(socket_strerror($error_id));

}

}elseif ($result===0){//客户端关闭

echo $client."客户端关闭\n";

unset($client_arr[$client]);

}else {

echo $client."客户端发送消息:".$data."\n";

socket_write($client,$data,strlen($data));

}

}

usleep(1);//避免while true死循环卡死

}

除了使用socket函数可以创建一个tcp服务器外,我们还可以通过steam流函数创建:<?php

$listen_host = '0.0.0.0';

$port = '8080';

$tcp_socket = stream_socket_server("tcp://{$listen_host }:$port", $errno, $errstr);

//直接创建一个监听tcp的套接字

$tcp_socket || die("$errstr ($errno)\n");

stream_set_blocking($tcp_socket, 0);//设置非阻塞

$client_arr = [];

while (1) {

set_error_handler(function(){});//socket错误拦截

$connection = stream_socket_accept($tcp_socket,0,$remote_address);

restore_error_handler();

if ($connection) {//如果有新链接,则处理新链接

echo $connection . "连接成功\n";

$client_arr[$connection] = $connection;

stream_set_blocking($connection, 0);//设置客户端非阻塞

}

//处理客户端

foreach ($client_arr as $client){

$data = fread($client, 65535);

if ($data === '' || $data === false) {

if ( (feof($client)  || $buffer === false)) {//客户端关闭

echo $client."客户端关闭\n";

unset($client_arr[$client]);

}

}

if(!empty($data)){

fwrite($client,$data);//发送给客户端

echo $client."客户端发送消息:".$data."\n";

}else{

continue;

}

}

usleep(1);//避免while true死循环卡死

}

php实现tcp客户端

tcp客户端的实现步骤是:

先创建一个tcpsocket

通过socket_connect连接

接收/发送消息<?php

$host='192.168.159.1';

$port='8080';

$client_socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);//创建一个tcp的socket

$connection = socket_connect($client_socket,$host,$port);//连接

socket_write($client_socket, "hello socket") or die("Write failed\n"); // 数据传送 向服务器发送消息

while(1){

$buffer = socket_read($client_socket, 1024, PHP_BINARY_READ);//默认阻塞类型,没有消息会一直阻塞

if (empty($buffer)){

die("已断开");

}

echo "服务端发送:".$buffer.PHP_EOL;

}

同样,我们可以通过流函数进行创建一个tcp客户端:<?php

$host='192.168.159.1';

//$host = '127.0.0.1';

$port = '8080';

$client_socket = stream_socket_client("tcp://$host:$port", $errno, $errstr, 30);

fwrite($client_socket, "hello socket");

while (!feof($client_socket)) {

$buffer = fread($client_socket,255);//默认阻塞类型,没有消息会一直阻塞

if(empty($buffer)){

echo "客户端关闭\n";

fclose($client_socket);

break;

}

echo "服务端发送:" . $buffer . PHP_EOL;

sleep(1);

}

php实现udp服务端

udp是无连接的协议,我们不需要去额外的创建客户端的socket进行一对一的传输,直接可通过创建udp服务端的socket,接收/发送所有的客户端:<?php

$listen_host = '0.0.0.0';

$port = '8080';

if (($udp_socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) == FALSE) {

$errorcode = socket_last_error();

$errormsg = socket_strerror($errorcode);

die("创建udp socekt失败: [$errorcode] $errormsg");

}

socket_bind($udp_socket,$listen_host,$port)||die('bind error');

while(1){

$data = socket_recvfrom($udp_socket, $buf, 512, 0, $remote_ip, $remote_port);

var_dump(base64_decode($buf));//udp直接发送中文将会出现乱码问题,可通过传输pack二进制包或者base64等方法解决

$msg="客户端发送的是:".$buf;

$msg.="客户端ip:".$remote_ip;

$msg.="客户端端口:".$remote_port;

//Send back

socket_sendto($udp_socket, $msg, strlen($msg), 0, $remote_ip, $remote_port);

}

同样,我们可以通过流函数创建udp服务端:<?php

$listen_host = '0.0.0.0';

$port = '8080';

$socket = stream_socket_server("udp://{$listen_host }:{$port}", $errno, $errstr, STREAM_SERVER_BIND);

if (!$socket) {

die("$errstr ($errno)");

}

do {

//接收客户端发来的信息

$inMsg = stream_socket_recvfrom($socket, 1024, 0, $peer);//udp无需握手,不需要获取客户端一对一获取数据,直接接收

//服务端打印出相关信息

echo "Client : $peer\n";

echo "Receive : {$inMsg}\n";

//给客户端发送信息

$outMsg = "$inMsg";

stream_socket_sendto($socket, $outMsg, 0, $peer);

} while ($inMsg !== false)

在上面的实现过程中,recvfrom都是阻塞的,这种情况会造成我们无法主动给客户端发送消息,我们可以参考tcp服务器的非阻塞实现,进行修改代码

php实现udp客户端

通过udp实现服务端的代码,我们可以发现:

只要有服务端的ip和端口(废话,没端口怎么通信),我们就可以用udp服务端的代码当成udp客户端使用(需要注意recvfrom阻塞问题).<?php

$listen_host = '0.0.0.0';

$port = '8080';

if (($udp_socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) == FALSE) {

$errorcode = socket_last_error();

$errormsg = socket_strerror($errorcode);

die("创建udp socekt失败: [$errorcode] $errormsg");

}

socket_bind($udp_socket,$listen_host,$port)||die('bind error');

socket_set_nonblock($udp_socket);//设置非阻塞

while(1){

$remote_ip='192.168.159.1';

$remote_port="8080";

$msg="I'm client";

//Send back

socket_sendto($udp_socket, $msg, strlen($msg), 0, $remote_ip, $remote_port);//每隔一秒给192.168.159.1发送数据

sleep(1);

}

除了使用服务端代码可以实现,我们也可以用客户端代码实现:<?php

$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);

$msg = 'hello';

$len = strlen($msg);

socket_sendto($socket, $msg, $len, 0, '192.168.159.1', 8080);

while(1){

$data = socket_recvfrom($socket, $buf, 512, 0, $remote_ip, $remote_port);

var_dump(base64_decode($buf));//udp直接发送中文将会出现乱码问题,可通过传输pack二进制包或者base64等方法解决

$msg="客户端发送的是:".$buf;

$msg.="客户端ip:".$remote_ip;

$msg.="客户端端口:".$remote_port;

//Send back

socket_sendto($socket, $msg, strlen($msg), 0, $remote_ip, $remote_port);

sleep(1);

}

流函数创建:<?php

$host='192.168.159.1';

$port = '8080';

$client_socket = stream_socket_client("udp://$host:$port", $errno, $errstr, 30);

fwrite($client_socket, "hello socket");

while (!feof($client_socket)) {

$buffer = fread($client_socket,255);//默认阻塞类型,没有消息会一直阻塞

echo "服务端发送:" . $buffer . PHP_EOL;

sleep(1);

}

本文为仙士可原创文章,转载无需和我联系,但请注明来自仙士可博客www.php20.cn

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值