socket通信
对TCP/IP、UDP、Socket编程这些词你不会很陌生吧?随着网络技术的发展,这些词充斥着我们的耳朵。大家能回答下面几个问题吗?
1.什么是TCP/IP、UDP?
2. Socket在哪里呢?
3. Socket是什么呢?
4. 怎么使用socket编程?
TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的。
UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是属于TCP/IP协议族中的一种。
这里有一张图,表明了这些协议的关系。
TCP/IP协议族包括运输层、网络层、链路层。现在你知道TCP/IP与UDP的关系了吧。 UDP是属于TCP/IP协议族中的一种
在上图中,我们没有看到Socket的影子,那么它到底在哪里呢?请看下图,一目了然。
**原来Socket在这里 **
Socket是应用层与TCP/IP协议族通信的中间软件抽象层。
它是一组接口。
在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP /IP协议族隐藏在Socket接口后面。
对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
听到Socket编程,是不觉得它是比较高深的编程知识呢?但是只要弄清Socket编程的工作原理,神秘的面纱也就揭开了。 请看下图:
先从服务器端说起。
服务器端先初始化Socket,
然后与端口绑定(bind),
对端口进行监听(listen),
调用accept阻塞,等待 客户端连接。
在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。
客户端发送数据请求(write),服务器端接收请求(read)并处理请求,然后把回应数据发送给客户端(write),客户端读取数据(read),最后关闭连接,一次交互结束。
搞懂socket通信流程了吧?来,对照scoket通信流程图,代码撸起!
首先,服务端代码Server.php如下:
//确保在连接客户端时不会超时
set_time_limit(0);
$ip = '127.0.0.1';
$port = 8888;
/*
+-------------------------------
* @socket通信整个过程
+-------------------------------
* @socket_create 1.初始化Socket
* @socket_bind 2.端口绑定(bind)
* @socket_listen 3.对端口进行监听(listen)
* @socket_accept 4.调用accept阻塞,等待 客户端连接
* @socket_read 5.接收客户端请求数据
* @socket_write 6.回应数据发送给客户端
* @socket_close 7.关闭连接
+--------------------------------
*/
/*---------------- 1.初始化Socket -------------------*/
//创建服务端的socket套接流,net协议为IPv4,protocol协议为TCP
$socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
/*---------------- 2.端口绑定(bind) -------------------*/
/*绑定接收的套接流主机和端口,与客户端相对应*/
if(socket_bind($socket,$ip,$port) == false){
echo 'server bind fail:'.socket_strerror(socket_last_error());
/*这里的127.0.0.1是在本地主机测试,你如果有多台电脑,可以写IP地址*/
}
/*---------------- 3.对端口进行监听(listen) -------------------*/
//监听套接流
if(socket_listen($socket,4)==false){
echo 'server listen fail:'.socket_strerror(socket_last_error());
}
/*---------------- 4.调用accept阻塞,等待 客户端连接 -------------------*/
//让服务器无限获取客户端传过来的信息
do{
/*接收客户端传过来的信息*/
$accept_resource = socket_accept($socket);
/*socket_accept的作用就是接受socket_bind()所绑定的主机发过来的套接流*/
if($accept_resource !== false){
/*读取客户端传过来的资源,并转化为字符串*/
/*----------5.接收客户端请求数据-----------*/
$string = socket_read($accept_resource,1024);
/*socket_read的作用就是读出socket_accept()的资源并把它转化为字符串*/
echo 'server receive is :'.$string.PHP_EOL;//PHP_EOL为php的换行预定义常量
if($string != false){
$return_client = 'server receive is : '.$string.PHP_EOL;
/*向socket_accept的套接流写入信息,也就是回馈信息给socket_bind()所绑定的主机客户端*/
/*------6.回应数据发送给客户端-----------*/
socket_write($accept_resource,$return_client,strlen($return_client));
/*socket_write的作用是向socket_create的套接流写入信息,或者向socket_accept的套接流写入信息*/
}else{
echo 'socket_read is fail';
}
/*socket_close的作用是关闭socket_create()或者socket_accept()所建立的套接流*/
socket_close($accept_resource);
}
}while(true);
socket_close($socket);
运行server.php,启动socket服务端
php server.php
现在服务端的程序已经开始运行,端口已经开始监听了
客户端client.php代码如下:
//初始化一个Socket 创建一个socket套接流
$socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
/****************设置socket连接选项,这两个步骤你可以省略*************/
//接收套接流的最大超时时间1秒,后面是微秒单位超时时间,设置为零,表示不管它
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 1, "usec" => 0));
//发送套接流的最大超时时间为6秒
socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array("sec" => 6, "usec" => 0));
/****************设置socket连接选项,这两个步骤你可以省略*************/
//连接服务端的套接流,这一步就是使客户端与服务器端的套接流建立联系
if(socket_connect($socket,'127.0.0.1',8888) == false){
echo 'connect fail massege:'.socket_strerror(socket_last_error());
}else{
$message = 'l love you 我爱你 socket';
//转为GBK编码,处理乱码问题,这要看你的编码情况而定,每个人的编码都不同
$message = mb_convert_encoding($message,'GBK','UTF-8');
//向服务端写入字符串信息
if(socket_write($socket,$message,strlen($message)) == false){
echo 'fail to write'.socket_strerror(socket_last_error());
}else{
echo 'client write success'.PHP_EOL;
//读取服务端返回来的套接流信息
while($callback = socket_read($socket,1024)){
echo 'server return message is:'.PHP_EOL.$callback;
}
}
}
socket_close($socket);//工作完毕,关闭套接流
运行client.php代码:
php client.php
至此客户端已经连接上服务端了,并和服务端通信了。
赶快本地代码撸起来,运行看下结果哦