我之前一直不明白一个问题(应用层协议是怎么选择tcp还是udp传输协议的?),最近看了socket好像有点明白了.
我的理解是这样的,socket是TCP/IP的封装,TCP/IP本身就是传输层协议,管的就是如何传输,其实当我们在建立socket套接字的时候(socket_create(AF_INET, SOCK_STREAM, SOL_TCP)),这个SOL_TCP其实就是选择了传输层协议是TCP了,那现在又有一个问题了,socket和Http或者websocket协议有啥关系呢,其实这些协议的底层用的都是socket
那socket是个啥东东呢?看两张图片我们就能知道了
TCP/IP是传输层协议,主要解决数据如何在网络中传输;而Http是应用层协议,主要解决如何包装数据。
Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。
我用php初步演示一下
//Service.php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '0.0.0.0', 8888);
socket_listen($socket);
$accept = socket_accept($socket);
$data = socket_read($accept, '1024');
echo $data;
//Client.php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, '127.0.0.1', 8888);
socket_write($socket, '服务端');
上面的最简单的实现了一下sokect,但是当我们用cli的形式去使用时,会出现个问题,第一个问题,当我执行一次client,客户端和服务端就自动关闭了,这要咋解决呢,其实这个也简单,闲话少说,上代码
<?php
// client.php
$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);
$data = socket_read($socket, '1024');
echo $data;
}
<?php
//Service.php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '0.0.0.0', 8888);
socket_listen($socket);
while (true) {
$accept = socket_accept($socket);
while (true) {
$data = socket_read($accept, '1024');
socket_write($accept, '我是服务端,我给客户端发信息');
echo $data.PHP_EOL;
}
}
上面的两段代码就解决了问题,一个客户端连接一个服务端,客户端可以发送任意数据,让服务端接收,服务端也会返回数据,但是又出现了一个问题,如果我开启多个客户端给服务端发送消息,那服务端就只能处理第一个了,那我们接下来要处理现在的问题了,怎么才能让多个客户端连接服务端,正常的发送消息呢?
<?php
// client.php
$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);
$data = socket_read($socket, '1024');
echo $data;
}
<?php
// service.php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '0.0.0.0', 8888);
socket_listen($socket);
$sockets[] = $socket;
$write = null;
$except = null;
while (true) {
$tmp_sockets = $sockets;
socket_select($tmp_sockets, $write, $except, null);
foreach ($tmp_sockets as $sock) {
if ($sock == $socket) {
$conSock = socket_accept($socket);
$sockets[] = $conSock;
} else {
$data = socket_read($sock, '1024');
socket_write($sock, '我是服务端,我给客户端发信息');
echo $data.PHP_EOL;
}
}
}