作者:这个昵称能用嘛 | 来源:互联网 | 2023-07-10 15:03
本文转载于我的个人博客,原文地址www.codeover.cnphp-socket欢迎来访socket介绍实现网络进程之间的通信,几乎所有应用程序都是采用socket,socket
本文转载于我的个人博客,原文地址 www.codeover.cn/php-socket/ 欢迎来访
socket介绍
实现网络进程之间的通信,几乎所有应用程序都是采用 socket,socket 是应用层与 TCP/IP 协议族通信的中间抽象层,它是一组接口。在设计模式中,socket 其实是一个门面模式,它把复杂的 TCP/IP 协议族隐藏在 socket 接口后面,对用户来说,一组简单的接口就是全部,让 socket 去组织数据,以符合指定的协议
socket 的英文原意是 「孔」或「插座」,通常也被称作「套接字」,用于描述 IP 地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。
socket 链接的三个过程
- 服务端监听:IP+端口号
- 客户端请求:发出向服务端的 IP 以及端口的连接请求
- 链接确认:服务端套接字监听到或者说接收到客户端套接字连接请求,他就会建立一个新的进程,把服务端的套接字描述发给客户端,以响应客户端的请求,一旦客户端确认了此描述,连接就建立好了。儿服务端的套接字继续处于监听状态,继续接受其他客户端套接字的连接请求。
php实现socket
如果需要在 php 中使用 socket,则需要在编译 php 是添加 --enable-sockets
配置项来启用,可使用 php -m|grep sockets
命令检查启用情况,具体编译过程可参考 这篇文章
快速体验
服务端与客户端简略代码如下,运行后服务端会阻塞等待客户端连接,客户端会在控制台要求输入内容,输入后信息会在服务端打印,同时客户端显示转为大写的内容,此示例服务端与客户端运行在一台服务器:
服务端监听
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, true);
socket_bind($socket, 0, 8888);
socket_listen($socket);
while (true) {
$conn_sock = socket_accept($socket);
socket_getpeername($conn_sock, $ip, $port);
while (true) {
$msg = socket_read($conn_sock, 10240);
socket_write($conn_sock, strtoupper($msg));
echo $msg;
}
}
客户端连接
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, '127.0.0.1', 8888);
while (true) {
fwrite(STDOUT, '请输入内容:');
$in = fgets(STDIN);
socket_write($socket, $in);
$msg = socket_read($socket, 10240);
echo $msg;
}
语法解释
socket_create
socket_create(int $domain,int $type, int $protocol): resource|false
创建并返回一个套接字资源,通常也称作一个通讯节点。一个典型的 socket 由至少 2 个套接字组成,其中一个运行在客户端,一个运行在服务端。
参数:
返回值
socket_create()
正确时返回一个套接字资源,失败时返回 false
。可以调用 socket_last_error()
获取错误码,错误码可以通过 socket_strerror(int $err_no)
转换为文字的错误说明。
socket_bind
socket_bind(resource $socket, string $address [, int $port]): bool
绑定一个地址与端口到套接字
参数:
socket
使用 socket_create()
创建的套接字资源
address
如果套接字是 AF_INET
族,那么 address
必须是一个四点法的 IP 地址,例如 127.0.0.1
、0.0.0.0
如果套接字是 AF_UNIX
族,那么 address
是 Unix 套接字一部分(例如 /tmp/my.sock
)
port
(可选)
该参数仅用于使用 AF_INET
族时,指定当前套接字监听的端口号
返回值:
绑定成功返回 true
,失败时则返回 false
,同 socket_create
,在绑定失败时可以调用 socket_last_error()
获取错误码,错误码可以通过 socket_strerror(int $err_no)
转换为文字的错误说明。
socket_listen
socket_listen(resource $socket [, int $backlog]): bool
在使用 socket_create()
创建套接字并使用 socket_bind()
将其绑定到名称之后,可能会告诉它侦听套接字上的传入连接。该函数仅适用于 SOCK_STREAM
或 SOCK_SEQPACKET
类型的套接字。
参数:
socket
使用 socket_create()
创建的套接字资源backlog
最大数量的积压传入连接将排队等待处理,如果连接请求到达时队列已满,则客户端可能会收到指示为 ECONNREFUSED
的错误。或者,如果底层协议支持重传,则可能会忽略该请求,以便重试可能会成功。
返回值:
绑定成功返回 true
,失败时则返回 false
,可以调用 socket_last_error()
获取错误码,错误码可以通过 socket_strerror(int $err_no)
转换为文字的错误说明。
socket_accept
socket_accept(resource $socket): resource|false
当有新的客户端连接时,返回一个新的 socket 资源以用于与客户端通信,如有多个连接排队,则返回第一个连接,相反如果没有待处理的连接,该函数会默认阻塞当前进程,直至新的客户端连接、断开
参数:
socket
使用 socket_create()
创建的套接字资源
返回值:
成功时返回一个新的套接字资源,错误时返回 false
,可以调用 socket_last_error()
获取错误码,错误码可以通过 socket_strerror(int $err_no)
转换为文字的错误说明。
socket_connect
socket_connect(resource $socket, string $address [, int $port = null]): bool
使用套接字实例发起到 address
的连接
参数:
socket
该参数必须是由 socket_create()
创建的 socket
实例
address
如果套接字是 AF_INET
族,那么 address
必须是一个四点法的 IP 地址,例如 127.0.0.1
如果支持 IPv6 并且套接字是 AF_INET6
,那么 address
也可以是一个有效的 IPv6 地址(例如 ::1
)
如果套接字是 AF_UNIX
族,那么 address
是 Unix 套接字一部分(例如 /tmp/my.sock
)
返回值:
成功时返回 true
, 或者在失败时返回 false
socket_write
socket_write(resource $socket, string $data [, int $length = null]): int|false
传输数据至指定套接字
参数:
返回值:
成功时返回成功发送的字节数,或者在失败时返回 false
,可以调用 socket_last_error()
与 socket_strerror(int $err_no)
获取具体错误信息
socket_read
socket_read(resource $socket, int $length, int $mode = PHP_BINARY_READ): string|false
从套接字资源内读取数据
参数:
socket
使用 socket_create()
或 socket_accept()
创建的套接字资源(服务端为 socket_accept()
客户端为 socket_create()
)
length
指定最大能够读取的字节数。否则您可以使用 \r
、\n
、\0
结束读取(根据 mode
参数设置)
mode
(可选)
PHP_BINARY_READ
(默认)- 使用系统的 recv()
函数。二进制安全地读取数据。
PHP_NORMAL_READ
- 读取到 \n
、\r
时停止。
返回值:
socket_read()
返回一个字符串,表示接收到的数据。如果发生了错误(包括远程主机关闭了连接),则返回 false
,可以调用 socket_last_error()
与 socket_strerror(int $err_no)
获取具体错误信息
socket_close
socket_close(resource $socket): void
关闭并销毁一个套接字资源
参数:
socket
使用 socket_create()
或 socket_accept()
创建的套接字资源
返回值:
无
Socket