因工作需要接触了socket,但socket是什么呢?很多人未必能说清楚,以下是我对socket的粗浅理解。
首先看一张图:
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。这段是别人对socket的总结,我认为socket是一个载体,它让TCP/UDP这些抽象的协议找到了一个可以具体使用的方法,通过socket就可以对这些协议进行使用。
了解socket的概念后,我们要尝试去使用它,我写了两个接口,一个是客户端的 client.php(发送和接收数据) 一个是服务器端的server.php(处理客户端的请求)
原理如下
通过这两个接口就可以实现客户端和服务器端的信息交流, 当然这是最简单的,一个网友告诉我,如果要用socket去做网络编程,那必须要考虑多线程,但是php是不支持多线程的。网上找到了一下解决办法,一般是用其他语言实现,具体可以参考PHP的swoole扩展 http://www.swoole.com/。
下面是完整代码:
服务器端:
<?php
/**
* @package : class.tool
* @classID : Server.class.php
* @author : 钟华宝
* @date : 2014-08-28
* 服务器端通信类
*/
class ServerSocket
{
private $server_port = '10051';//通信端口
private $address = 'http://192.168.2.119/';//通信地址
/**
* 构造函数
* @access public
*/
public function __construct()
{
}
/**
* 析构函数
* @access public
*/
public function __destruct()
{
}
/**
* 服务端接收和发送信息函数
* @access public
*/
public function server_Socket()
{
error_reporting(E_ALL);
set_time_limit(0);
//创建一个套接字(通讯节点)(指定协议,套接字类型,具体协议)
if( ($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) {
//echo "socket_create() failed :reason:" . socket_strerror(socket_last_error());
return false;
}
//绑定
if (socket_bind($sock, $this->address, $this->server_port) === false) {
//echo "socket_bind() failed :reason:" . socket_strerror(socket_last_error($sock));
return false;
}
//监听
if(socket_listen($sock, 5) === false){
echo "socket_bind() failed :reason:" . socket_strerror(socket_last_error($sock));
return false;
}
//不断循环
do {
//得到链接
if (($msgsock = socket_accept($sock)) === false) {
echo "socket_accepty() failed :reason:".socket_strerror(socket_last_error($sock)) . "\n";
return false;
}
$msg = 'server test\n';
//发送数据
socket_write($msgsock, $msg, strlen($msg));
//socket_write($msgsock, $msg, strlen($msg));
//接收数据
$buf = socket_read($msgsock, 8192);
$talkback = "received message:$buf<br />";
if (false === socket_write($msgsock, $talkback, strlen($talkback))) {
echo "socket_write() failed reason:" . socket_strerror(socket_last_error($sock));
return false;
}
else{
echo 'send success\n';
}
socket_close($msgsock);
} while(true);
socket_close($sock);
}
}
$ser = new ServerSocket();
$ser->server_Socket();
?>
客户端:
<?php
/**
* @package : class.tool
* @classID : Client.class.php
* @author : 钟华宝
* @date : 2014-08-28
* 客户端通信类
*/
class ClientSocket
{
private $server_port = '10051';//通信端口
private $address = 'http://192.168.2.119/';//通信地址
/**
* 构造函数
* @access public
*/
public function __construct()
{
}
/**
* 析构函数
* @access public
*/
public function __destruct()
{
}
/**
* 服务端接收和发送信息函数
* @access public
*/
public function client_Socket($Arr, $cat_type = '', $type = '')
{
//判断参数是否符合条件
if(empty($Arr)||!is_array($Arr)||$cat_type == ''){
return false;
}
else{
//将参数组装成数组
$content = array(
'arr' => $Arr,
'cat_type'=> $cat_type,
'type' => $type
);
}
$content = '111111111111';
//创建一个套接字(通讯节点)(指定协议,套接字类型,具体协议)
$socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
if ($socket === false) {
// echo "socket_create() failed: reason: " . socket_strerror(socket_last_error());
return false;
}
//开启一个套接字连接
$result = socket_connect($socket,$this->address,$this->server_port);
if ($result === false) {
//echo "socket_connect() failed.\nReason: ($result) " . socket_strerror(socket_last_error($socket));
return false;
}
//发送数据
socket_write($socket,$content,strlen($content));
//读取指定长度的数据
while ($out = socket_read($socket, 8192)) {
echo $out;
}
//关闭一个socket资源
socket_close($socket);
}
}
?>
windows 下服务器端需要在cli模式是执行,有可能cli模式下php.ini文件载入的不一样