上网查了查php实现socket编程的案例不是很多,刚开始接触socket并想了解他的时候我的头都大了,什么是socket编程......好吧,我就说说我是怎么入坑的。
我们先说说什么是socket,他就是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
学习socket编程我们先来看看php中提供的socket系列函数,弄清他的意思我们就能更好地实现功能了。这里简单的说一下常用的函数,想看更详细的就在php在线手册中自行阅读。
1、socket_create(int $domain , int $type , int $protocol)
创建一个网络数据流。他的返回值是一个套接字,或者false。要读取错误代码,可以调用socket_last_error()。这个错误代码可以通过 socket_strerror() 读取文字的错误说明。socket_create创建并返回一个套接字,也称作一个通讯节点。一个典型的网络连接由 2 个套接字构成,一个运行在客户端,另一个运行在服务器端。
domain:指我们选择哪一个协议用在创建的套接字上
AF_INET:IPV4网络协议。TCP和UDP都可以使用此协议。
AF_INET6:IPV6网络协议。TCP和UDP都可以使用此协议。
AF_UNIX : 本地通信协议。具有高性能和低成本的IPC(进程间通讯)。
type:用于选择套接字使用的类型。
SOCK_STREAM:提供一个顺序化的、可靠的、全双工的、基于连接的字节流。支持数据传送流量控制机制。TCP 协议即基于这种流式套接字。(以上是手册说的,其实说白了就是TCP协议使用它)。
SOCK_DGRAM:提供数据报文的支持。(无连接,不可靠、固定最大长度).UDP协议即基于这种数据报文套接字。(就是UDP协议使用它)
还有三个我没怎么用过,可以自行去手册查看----SOCK_SEQPACKET、SOCK_RAW、SOCK_RDM。
protocol:是设置指定 domain 套接字下的具体协议。这个值可以使用 getprotobyname() 函数进行读取。如果所需的协议是 TCP 或 UDP,可以直接使用常量 SOL_TCP 和 SOL_UDP 。
2、socket_bind ( resource $socket , string $address [, int $port = 0 ] )
我们创建完套接字了,那么我们开始绑定地址了,他成功时返回 TRUE, 或者在失败时返回 FALSE。(注意:该操作必须是在使用 socket_connect() 或者 socket_listen() 建立一个连接之前。)
这里简单的说一下参数。
$socket :就是我们创建的套接字
$address :如果我们创建套接字用的是AF_INET族,那么我们就是用IP地址(127.0.0.1)。如果我们使用AF_UNIX族,我们使用Unix套接字一部分(/tmp/my.sock)。
$port :使用AF_INET时,可以填写端口号(127.0.0.1:6666)
3、socket_create_listen ( int $port [, int $backlog = 128 ] )
看函数就知道他是用来监听的,$port :socket_create的函数返回值,$backlog:最大监听套接字个数。
4、socket_accept ( resource $socket )
他的作用是接收套接字的资源信息,也就是阻塞。他的返回值是成功返回套接字的信息资源,失败为false
5、socket_read ( resource $socket , int $length [, int $type = PHP_BINARY_READ ] )
他的作用是接收客户端传来的数据,你可以理解为$_POST,不过这可不一样得呦~他的返回值: 成功把套接字的资源转化为字符串信息,失败为false
$socket:就是socket_create或者socket_accept的函数返回值。
$length :我们要读取的长度。
$type :PHP_BINARY_READ (Default) -:用系统默认的函数recv()来读取数据。
PHP_NORMAL_READ :读取数据停留在\n或者\r上。
6、socket_write ( resource $socket , string $buffer [, int $length = 0 ] )
他的作用是将想要传送的数据写入套接字中,你可以理解为传值。它的返回值是成功返回字符串的字节长度,失败为false。
$socket:就是socket_create或者socket_accept的函数返回值。
$buffer:要写入缓冲区的数据。
$length : 可选参数长度可以指定写入套接字的备用字节长度。如果此长度大于缓冲区长度,则将其静默截断为缓冲区的长度
7、socket_close ( resource $socket )
顾名思义,关闭连接释放资源。
在这里补充一个函数,我们这篇文章主要说的是websocket的实现,不过我们也可以利用后端php实现一个客户端,那么我们就会用到这个函数。
8、socket_connect ( resource $socket , string $address [, int $port = 0 ] )(客户端使用)
他是开启一个套接字连接,返回值为true或者false。他是在你建立好socket连接之后进行连接的。参数详见socket_bind()(服务器端使用)函数.
额......想了好久还是把函数意思附带上吧(避免我再搜索,记忆力太差了)。
socket_accept() 接收一个socket连接
socket_bind() 把socket绑定在一个IP地址和端口上
socket_clear_error() 清除socket的错误或者最后的错误代码
socket_close() 关闭一个socket资源
socket_connect() 开始一个socket连接
socket_create_listen() 在指定端口打开一个socket监听
socket_create_pair() 产生一对没有区别的socket到一个数组里
socket_create() 产生一个socket,相当于产生一个socket的数据结构
socket_get_option() 获取socket选项
socket_getpeername() 获取远程类似主机的ip地址
socket_getsockname() 获取本地socket的ip地址
socket_iovec_add() 添加一个新的向量到一个分散/聚合的数组
socket_iovec_alloc() 这个函数创建一个能够发送接收读写的iovec数据结构
socket_iovec_delete() 删除一个已经分配的iovec
socket_iovec_fetch() 返回指定的iovec资源的数据
socket_iovec_free() 释放一个iovec资源
socket_iovec_set() 设置iovec的数据新值
socket_last_error() 获取当前socket的最后错误代码
socket_listen() 监听由指定socket的所有连接
socket_read() 读取指定长度的数据
socket_readv() 读取从分散/聚合数组过来的数据
socket_recv() 从socket里结束数据到缓存
socket_recvfrom() 接受数据从指定的socket,如果没有指定则默认当前socket
socket_recvmsg() 从iovec里接受消息
socket_select() 多路选择
socket_send() 这个函数发送数据到已连接的socket
socket_sendmsg() 发送消息到socket
socket_sendto() 发送消息到指定地址的socket
socket_set_block() 在socket里设置为块模式
socket_set_nonblock() socket里设置为非块模式
socket_set_option() 设置socket选项
socket_shutdown() 这个函数允许你关闭读、写、或者指定的socket
socket_strerror() 返回指定错误号的详细错误
socket_write() 写数据到socket缓存
socket_writev() 写数据到分散/聚合数组
哈哈 快写完了(写个笔记比学的都累┭┮﹏┭┮)。那么我们开始用一个例子结束这篇博客吧~~~~
客户端的代码如下:
//例子中的参数不记得可以翻阅上面进行阅读
//设置地址和端口
$address = '127.0.0.1';
$port = 666;
//确保PHP在等待客户端连接时不会超时
set_time_limit(0);
//创建服务器端socket套接字。
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
//在套接字上绑定地址与端口
if(socket_bind($socket, $address,$port) == false){
echo 'servce bind fali :'.socket_strerror(socket_last_error()).PHP_EOL;
}else{
echo 'servce bind success'.PHP_EOL;
}
//进行监听
if(socket_listen($socket) == false){
echo 'servce listen fail:'.socket_strerror(socket_last_error()).PHP_EOL;
}else{
echo 'servce listen success'.PHP_EOL;
}
//下面我们进行挂起,使得服务器端可以随时接收到请求
do{
//等待连接请求,接收绑定的客户端发来的信息
$accept_resource = socket_accept($socket);
if($accept_resource !==false){
//读取客户端发来的信息,转化为字符串。
$resource = socket_read($accept_resource, 1024);
echo 'receive:'.$resource.PHP_EOL;
if($resource !== false){//这里可以根据你搜需要的业务进行判断
//给客户端返回想要传输的数据
$return = 'connect success';
socket_write($accept_resource,$return,strlen($return));
}else{
echo 'read fail';
}
}
}
//使得服务器端挂起
while(true);
//关闭连接
socket_close($socket);
?>
接下来是客户端代码:
$address = '127.0.0.1';
$port = 666;
//设置无限请求超时时间
set_time_limit(0);
//创建服务器端socket套接字。
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, $address,$port);
echo 'connect success'.PHP_EOL;
$return = 'i am client'.PHP_EOL;
socket_write($socket, $return , strlen($return));
$msg = socket_read($socket, 1024);
echo 'resource:'.$msg.PHP_EOL;
socket_close($socket);
echo "close OK\n";
?>
小伙伴们写文章(笔记不容易呀),有什么问题可以联系我。共同进步,共同成长。
文章例子代码:https://github.com/cwb2819259/PHP_SOCKET.git
文章借鉴:http://php.net/manual/zh/book.sockets.php