编程语言
C#编程语言基础
C#面向对象与多线程
C#数据及文件操作
JavaScript基础
JavaScript的数据类型和变量
JavaScript的运算符和表达式
JavaScript的基本流程控制
JavaScript的函数
JavaScript对象编程
JavaScript内置对象和方法
JavaScript的浏览器对象和方法
JavaScript访问HTML DOM对象
JavaScript事件驱动编程
JavaScript与CSS样式表
Ajax与PHP
ECMAScript6的新特性
Vue.js前端开发
PHP的常量与变量
PHP的数据类型与转换
PHP的运算符和优先规则
PHP程序的流程控制语句
PHP的数组操作及函数
PHP的字符串处理与函数
PHP自定义函数
PHP的常用系统函数
PHP的图像处理函数
PHP类编程
PHP的DataTime类
PHP处理XML和JSON
PHP的正则表达式
PHP文件和目录处理
PHP表单处理
PHP处理Cookie和Session
PHP文件上传和下载
PHP加密技术
PHP的Socket编程
PHP国际化编码
MySQL数据库基础
MySQL数据库函数
MySQL数据库账户管理
MySQL数据库基本操作
MySQL数据查询
MySQL存储过程和存储函数
MySQL事务处理和触发器
PHP操作MySQL数据库
数据库抽象层PDO
Smarty模板
ThinkPHP框架
Python语言基础
Python语言结构与控制
Python的函数和模块
Python的复合数据类型
Python面向对象编程
Python的文件操作
Python的异常处理
Python的绘图模块
Python的NumPy模块
Python的SciPy模块
Python的SymPy模块
Python的数据处理
Python操作数据库
Python网络编程
Python图像处理
Python机器学习
TensorFlow深度学习
Tensorflow常用函数
TensorFlow用于卷积网络
生成对抗网络GAN
要用PHP进行Socket编程,需要加载PHP扩展,Socket库。一般安装包内的扩展库已经包括php_sockets.dll,在windows下加载Socket库很简单,只需要在PHP配置文件php.ini中找到:
;extension=php_sockets.dll
将其改为:
extension=php_sockets.dll
即可。即把这条语句前面的注释去掉。然后重启Apache,运行phpinfo(),看看有没有Socket库说明,可以知道是否成功加载了Socket库。
2.Socket原理:
Socket不过是一个数据结构,可以用此去开始一个客户端和服务器之间的会话。会话中的服务器会一直监听网络,随时准备产生一个新的会话。如果有客户端连接请求并且服务器端接受了客户端的连接请求,那么就开始进行会话。这时,如果客户端能够发生信息到服务器,服务器也能发送信息给客户端。
要创建一个Socket,需要三个变量:一个协议、一个Socket类型和一个公共协议类型。
下表列出了Socket协议类型:
协议 |
说明 |
AF_INET |
这是大多数用来产生Socket的协议,使用TCP或UDP来传输,用于IPv4地址 |
AF_INET6 |
与上面类似,不过用于IPv6的地址 |
AF_UNIX |
本地协议,使用在Unix和Linux系统上,很少使用,当客户端和服务器在同一台机器上时使用 |
下表列出了Socket类型:
类型 |
说明 |
SOCK_STREAM |
建立按顺序的、可靠的、数据完整的、基于字节流的连接,使用最多,用TCP来进行传输 |
SOCK_DGRAM |
无连接的、固定长度的传输调用,是不可靠的,使用UDP进行连接 |
SOCK_SEQPACKET |
建立双线路的可靠连接,发送固定长度的数据包进行传输,必须把这个包完整接收才能进行读取 |
SOCK_RAW |
提供单一的网络访问,使用ICMP公共协议(ping、traceroute使用该协议) |
SOCK_RDM |
很少使用,在大多数操作系统上没有实现,提供给数据链路层使用,不保证数据包的顺序 |
下表列出了可选择的公共协议类型:
协议 |
说明 |
ICMP |
互联网控制消息协议,主要使用在网关和主机上,用来检查网络状态和报告错误信息 |
UDP |
用户数据报文协议,是一个无连接的不可靠的传输协议 |
TCP |
传输控制协议,是使用最多的可靠的公共协议,保证数据包能够到达接收者那里。如果在传输过程中发生错误,将重新发送数据包 |
3.Socket函数和用法:
可以在PHP中使用socket_create()函数来产生一个Socket,这个函数需要三个参数,运行成功返回一个包含Socket的资源类型,没有成功则返回false。语法格式:
resource socket_create(int protocol, int socketType, int commonProtocol);
然后,就能够使用操作Socket的内建函数。这些内建函数能够绑定Socket到一个IP,监听一个Socket的通信,接收一个Socket。示例:
<?php
$commonProtocol=getprotobyname('tcp');
$socket=socket_create(AF_INET, SOCK_STREAM, $commonProtocol);
socket_bind($socket, 'localhost', 1337);
socket_listen($socket);
//其他Socket操作
?>
上面的代码产生了一个服务器端,其中getprotobyname()使用公共协议名字来获取一个协议类型,这里使用的是TCP公共协议。也可以使用:
$socket=socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
来替代上述代码的前两行。后面的代码是产生一个Socket并且返回一个Socket资源,然后把Socket绑定到一个IP地址和某一个端口上,接着监听所有进来的Socket连接。
下表列出部分常用的PHP中的Socket内建函数:
函数 |
说明 |
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() |
创建一个能够发送、接收和读写的输入/输出数据向量数据结构 |
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() |
写入数据到分散/聚合数组 |
4.Socket实例:
①简单Socket服务器simple_server.php:
<?php
$commonProtocol=getprotobyname('tcp');
$socket=socket_create(AF_INET, SOCK_STREAM, $commonProtocol);
socket_bind($socket, 'localhost', 1234);
socket_listen($socket);
//接受连接
$conn=socket_accept($socket);
$msg="成功连接到socket……";
$msg=iconv('utf-8', 'gbk', $msg);
if ($conn) {
socket_write($conn, "$msg\n\r");
}
//关闭连接
socket_close($conn);
?>
应该使用命令提示符来运行上面的实例,因为这里将产生一个服务器,而不是一个网页。如果尝试使用Web浏览器来运行这个脚本,有可能运行时间会超过30秒的限时。当然,也可以设置一个无限的运行时间:
set_time_limit(0);
当然最好还是使用命令提示符来运行脚本:
php.exe simple_server.php
如果没有在系统的环境变量中设置php解释器的路径,就需要给php.exe指定详细的路径。当运行这个服务器端时,就能够通过远程登录Telnet的方式连接到端口1234来测试这个服务器。
telnet localhost 1234
需要注意,要在命令行下正确显示中文,需要把$msg改为gbk编码,因为windows命令行的字符编码是gbk。可以通过使用gbk编码来编写脚本,从而避免中文乱码。如果脚本不是gbk,就需要用iconv函数对$msg进行编码转换,这样才能看到正确的信息。
②交互式的服务器:
<?php
//创建Socket
$commonProtocol=getprotobyname('tcp');
if ($socket=socket_create(AF_INET, SOCK_STREAM, $commonProtocol)===false) {
echo "socket_create()错误:".socket_strerror(socket_last_error())."\n";
}
//绑定端口
$addr='localhost';
$port=1234;
if (socket_bind($socket, $addr, $port)===false) {
echo "socket_bind()错误:".socket_strerror(socket_last_error())."\n";
}
//监听
if (socket_listen($socket)===false) {
echo "socket_listen()错误:".socket_strerror(socket_last_error())."\n";
}
//设置欢迎信息
$msg="欢迎连接PHP socket服务器。\r\n"."要退出连接可以输入'quit';\r\n"."要关闭服务器请输入'shutdown'.\r\n";
//编码转换
$msg=iconv('utf-8', 'gbk', $msg);
while (true) {
//接受所有的连接请求
if ($conn=socket_accept($socket)===false) {
echo "socket_accept()错误:".socket_strerror(socket_last_error())."\n";
break;
}
//检查是否有欢迎信息,如果有则在客户连接后输出
if ($msg!="") {
socket_write($conn, "$msg\n\r");
}
//读取输入
while (true) {
//读取提示符
$prompt='PHP Server>';
socket_write($conn, $prompt);
if (false===($buf=socket_read($conn, 2048, PHP_NORMAL_READ))) {
echo "socket_read()错误:".socket_strerror(socket_last_error())."\n";
break 2;
}
//剔除无意义的输入
if (!($buf=trim($buf))) {
continue;
}
//退出连接
if ($buf=='quit') {
break;
}
//关闭服务
if ($buf=='shutdown') {
//关闭连接并跳出循环
socket_close($conn);
break 2;
}
//反馈信息
$talkback="接收到输入:";
$talkback=iconv('utf-8', 'gbk', $talkback);
$talkback.=$buf.”\r\n”;
socket_write($conn, $talkback, strlen($talkback));
//服务器端记录
echo "$buf\n";
}
//关闭连接
socket_close($conn);
echo iconv('utf-8', 'gbk', '关闭连接')."\r\n\r\n";
}
//关闭服务
socket_close($socket);
?>
在使用“telnet localhost 1234”连接服务器后可以看到Socket服务端对输入的响应。