PHP的Socket编程

上网查了查php实现socket编程的案例不是很多,刚开始接触socket并想了解他的时候我的头都大了,什么是socket编程......好吧,我就说说我是怎么入坑的。

我们先说说什么是socket,他就是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

学习socket编程我们先来看看php中提供的socket系列函数,弄清他的意思我们就能更好地实现功能了。这里简单的说一下常用的函数,想看更详细的就在php在线手册中自行阅读。

1socket_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 。

2socket_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)

3socket_create_listen ( int $port [, int $backlog = 128 ] )

看函数就知道他是用来监听的,$port :socket_create的函数返回值,$backlog:最大监听套接字个数。

4socket_accept ( resource $socket )

他的作用是接收套接字的资源信息,也就是阻塞。他的返回值是成功返回套接字的信息资源,失败为false

5socket_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上。

6socket_write ( resource $socket , string $buffer [, int $length = 0 ] )

他的作用是将想要传送的数据写入套接字中,你可以理解为传值。它的返回值是成功返回字符串的字节长度,失败为false。

$socket:就是socket_create或者socket_accept的函数返回值。

$buffer:要写入缓冲区的数据。

$length : 可选参数长度可以指定写入套接字的备用字节长度。如果此长度大于缓冲区长度,则将其静默截断为缓冲区的长度

7socket_close ( resource $socket )

顾名思义,关闭连接释放资源。

在这里补充一个函数,我们这篇文章主要说的是websocket的实现,不过我们也可以利用后端php实现一个客户端,那么我们就会用到这个函数。

8socket_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

你可能感兴趣的:(PHP的Socket编程)