前言
swoole服务web访问
上节课主要说到了长连接、心跳检测机制、udp和tcp、异步扩展,需要注意的是异步扩展安装版本要一致,重点是udp和tcp的区别。udp特点:不负责任,只发送不管结果,tcp:专业,确定相互之间的通信,再去发送信息。udp 的速度快于tcp的,udp=》软件弹窗,群发=》微信公众号的群发。
tcp服务端,浏览器是无法直接访问的,但是我们可以通过浏览器访问tcp同步客户端,通过同步客户度来访问tcp服务端,来进行通信。
运行tcp服务端
//创建Server对象,监听 127.0.0.1:9501端口
$serv = new Swoole\Server("0.0.0.0", 9501);
//添加配置
$serv->set([
'heartbeat_idle_time' => 10,
'heartbeat_check_interval' => 3,
]);
//注册事件
$serv->on('Start',function ($serv) use($host){
echo "启动swoole 监听的信息tcp:$host:9501\n";
});
//监听连接进入事件
$serv->on('Connect', function ($serv, $fd) {
echo "Client: Connect.\n";
});
//监听数据接收事件
$serv->on('Receive', function ($serv, $fd, $from_id, $data) {
$serv->send($fd, "Server: ".$data);
});
//监听连接关闭事件
$serv->on('Close', function ($serv, $fd) {
echo "Client: Close.\n";
});
//启动服务器
$serv->start();
同步客户端
$client = new swoole_client(SWOOLE_SOCK_TCP);
//连接到服务器
if (!$client->connect('127.0.0.1', 9501, 0.5))
{
die("connect failed.");
}
function order(){
sleep(4);//某一些的操作造成的时间很长
return "order\n";
}
//向服务器发送数据
if (!$client->send(order()))
{
die("send failed.");
}
//从服务器接收数据
$data = $client->recv();
if (!$data)
{
die("recv failed.");
}
echo $data."\n";
//关闭连接
$client->close();
//另一个事情
//返回结果给用户
echo "
同步客户端,请求完,主动关闭连接,短链接\n";
swoole还有一个web服务器,可以完成上面的请求
web http服务端
$http = new Swoole\Http\Server("0.0.0.0", 9501);
$http->on('request', function ($request, $response) {
//var_dump($request->get, $request->post);
print_r($request->get);
$response->header("Content-Type", "text/html; charset=utf-8");
$response->end("Hello Swoole. #".rand(1000, 9999)."
");
});
$http->start();
运行之后
就可以直接通过浏览器访问服务端
但是,通常我们是不能直接访问服务端监听的9501端口的,我们都是访问ip:80这样的。
那这种是该怎么做呢?
这个时候,我们都是通过nginx反向代理,实现的。
接下来是配置nginx,实现反向代理。打开宝塔,点击网站,进行设置。打开配置文件,添加:
location / {
proxy_pass http://117.51.157.79:9501;
}
这个时候,直接访问ip,就可以了。
分层:4、5、7
为什么需要协议?
那么两者之间通信就需要大家都理解的一种协议。
那为什么还要分层呢?
计算机的协议就是 0 和 1,靠0 1进行通信。
假如现在有2台电脑需要通信,早期我们通过 光纤(网线)进行通信。
但是,只通信是不行的,通信需要数据。
那多台电脑是如何通信的呢?
是通过路由器进行通信的。需要的数据 是由head+data 组合成的数据,head里面 又由 通信源 和 接收源 组成。这个通信源和接收源 就是电脑的 mac地址 。这个mac地址 就是电脑的身份证号码 物理地址。
那路由器是怎么发送 数据的呢?
路由器 是通过 广播的方式 (输出全靠吼)来进行发送数据的。就是电脑B发送数据,通过路由器,会把数据 同时发送给电脑A和电脑C。通过 监听 ,A和C都可以接收到 B的信息 ,然后根据head 中的接收源 判断是否是自己的信息。
我们把 上面的 2台 电脑 一一对应的 称为 物理层 (网线)
多台电脑通信 需要路由器 以广播的形式 根据 mac 物理地址 进行通信 称为 链路层 (mac)
但是 通过mac地址 以广播的形式通信 ,电脑A发送数据,全国各地都有可能接收到,这样做是有坏处的,效率低 不安全。
这个时候 就诞生了 ip 协议。
这一层就是 网络层。
那 电脑 具体运行我们的程序 是通过什么来找到的呢?
这个时候就需要 端口 进行监听 确定程序。(端口号:0~65535)
那是怎么通过端口去访问呢?
通过tcp,udp协议来进行访问的,在head里加个tcp头或udp头。这一层叫 传输层。
在确定要运行的程序之后,还需要一个 应用层 去运行程序。
那应用层和传输层 是怎么通信的呢?
我们会在应用层 和传输层 之间 开启一个用户进程,通过socket套接字 进行相互之间的通信。
应用层 还会延伸出 http ssh ftp等协议 进行通信。
tcp通信 有长连接和短连接 ,通常认为是可靠的,那为什么呢?tcp通信的原理是什么呢?
tcp 连接 通信 会存在一个问题 是 粘包,这个是怎么产生的呢?
包 : 就是发送的数据 通常 都是通过tcp连接来 发送 数据
拆包 组包 分包
当 我们发送一个很小的数据包给客户时,直接发送即可。但是 当我们发送很大的数据包给客户时,例如1G的视频数据,这个时候回通过 特殊的方式 将数据包分成同样大小的小包,这种方式 叫 拆包 或 分包
客户接收到 小包时,会将小包 组合成 一个 大包,这种方式叫 组包。
在叫很多个小包发送给客户时,会存在 丢包 的问题。还有 抓包 的问题。
那粘包产生的原因是什么呢?
下面的例子 再现这个粘包的问题:
服务端
//创建Server对象,监听 127.0.0.1:9501端口
$serv = new Swoole\Server("0.0.0.0", 9501);
//添加配置
$serv->set([
'heartbeat_idle_time' => 10,
'heartbeat_check_interval' => 3,
]);
//注册事件
$serv->on('Start',function ($serv) use($host){
echo "启动swoole 监听的信息tcp:$host:9501\n";
});
//监听连接进入事件
$serv->on('Connect', function ($serv, $fd) {
echo "Client: Connect.\n";
});
//监听数据接收事件
$serv->on('Receive', function ($serv, $fd, $from_id, $data) {
echo "接收到客户的数据".$data."\n";
$serv->send($fd, "Server: ".$data);
});
//监听连接关闭事件
$serv->on('Close', function ($serv, $fd) {
echo "Client: Close.\n";
});
//启动服务器
$serv->start();
客户端
//同步客户端
$client = new swoole_client(SWOOLE_SOCK_TCP);
//连接到服务器
if (!$client->connect('127.0.0.1', 9501, 0.5))
{
die("connect failed.");
}
//向服务器发送数据
for($i=0;$i<100;$i++){
$client->send($i);
}
//从服务器接收数据
$data = $client->recv();
if (!$data)
{
die("recv failed.");
}
echo $data."\n";
//关闭连接
$client->close();
//另一个事情
//返回结果给用户
echo "
同步客户端,请求完,主动关闭连接,短链接\n";
正常的结果应该是
接收到客户端数据0
接收到客户端数据1
接收到客户端数据2
....
接收到客户端数据100
但是却出现了上面的情况,数据都粘在一起了 这种现象 就叫做 粘包。
延迟1秒 发送
那为什么会出现粘包呢?(粘包 是 正常现象)
在短时间内发送的数据之后,数据包就粘在一起,一起发送