提交 bcb34cd5 编写于 作者: xc13262215230's avatar xc13262215230

web服务器支持http长连接和短连接-keep-alive识别

上级 91b61c7a
......@@ -15,12 +15,15 @@ namespace doyou {
// 在间隔指定时间后才允许发送-定时发送
#define CLIENT_SEND_BUFF_TIME 200
// 服务器端客户端对象的状态
enum ClientState
{
ClientState_create = 10, // 对象被创建,未被使用(生产者线程刚刚创建)
ClientState_join,
ClientState_create = 10, // 对象被创建,未被使用(生产者线程(接收新客户端连接线程)刚刚创建对象)
// 分析:普通tcp连接,join状态和run状态达成条件一样无区别。http连接,join后,需要接收到客户端
// 一个完整的数据请求后,可以任务进入run状态。
ClientState_join, // 对象被消费者线程(与客户端实际业务通信服务线程)取走
ClientState_run,
ClientState_close,
ClientState_close, // 对象关闭状态,一般代表通信结束
};
......@@ -106,15 +109,20 @@ namespace doyou {
{
resetDTSend();
int ret = _sendBuff.write2socket(_sockfd);
// TMP: 发送完数据,立即主动关闭当前客户端
if (_sendBuff.DataLen() == 0) {
this->OnClose();
CELLLog_Info("socket[%d] OnClose positively.", _sockfd);
// 分析:在http短连接场景才会执行立即主动关关闭客户端动作
OnSendComplete();
}
return ret;
}
// 发送完成事件
// 后面会用到事件委托代理机制,也是比较好的方式,可以完成更多业务逻辑,当前的属于虚函数的方式更加简便
virtual void OnSendComplete()
{
}
//缓冲区的控制根据业务需求的差异而调整
//发送数据
int SendData(netmsg_DataHeader* header)
......@@ -209,7 +217,7 @@ namespace doyou {
void OnClose()
{
// 可以做更多操作:比如不会立即真正删除,以备高效复用等等
// todo more
CELLLog_Info("socket[%d] OnClose.", _sockfd);
State(ClientState_close);
}
......
......@@ -184,6 +184,15 @@ namespace doyou {
// 通过URL传递的参数和请求体传递的参数都接收
SplitUrlArgs(_recvBuff.data() + _headerLen);
}
// 根据请求头,做相应处理
// 分析:http客户端支持长连接,web服务器就建立长链接,不支持就建立短连接。
// web服务器兼容长连接和短连接两种case
char const* str = HeaderGetStr("Connection", "");
if (0 == strcmp("keep-alive", str) ||
0 == strcmp("Keep-Alive", str)) {
_keepAlive = true; // 设置建立长连接标识
}
return true;
}
......@@ -402,6 +411,27 @@ namespace doyou {
return def;
}
// 获取headerMap指定参数名key的数值val
char const* HeaderGetStr(char const* argName, char const* def) // auto sar c++14 std
{
auto itr = _headerMap.find(argName);
if (itr != _headerMap.end()) {
return itr->second;
}
else {
return def;
}
}
// 发送完成事件, 重写父类虚函数
virtual void OnSendComplete() override
{
if (!_keepAlive) {
OnClose();
}
// to do more
}
protected:
......@@ -417,6 +447,7 @@ namespace doyou {
char* _url_path = nullptr; // url路径
char* _url_args = nullptr; // url参数
char* _httpVersion = nullptr;
bool _keepAlive = false; // 长连接和短连接token
};
......
......@@ -55,22 +55,23 @@ namespace doyou {
CELLLog_Info("Server%d.Close end", _id);
}
//处理网络消息
// 处理网络消息
void OnRun(Thread* pThread)
{
while (pThread->isRun())
{
if (!_clientsBuff.empty())
{// 从缓冲队列里取出客户数据
std::lock_guard<std::mutex> lock(_mutex);
std::lock_guard<std::mutex> lock(_mutex); // 临界资源加锁保护,自解锁
for (auto pClient : _clientsBuff)
{
_clients[pClient->sockfd()] = pClient;
pClient->serverId = _id;
if (_pNetEvent) // 不为空表明已经注册,触发事件
if (_pNetEvent) // 不为空表明已经注册,触发事件(出发回调函数)
_pNetEvent->OnNetJoin(pClient);
OnClientJoin(pClient);
pClient->State(ClientState_join);
}
_clientsBuff.clear();
_clients_change = true;
......
......@@ -10,6 +10,7 @@ g++ server.cpp -std=c++11 -pthread -o EasyServer
//=====代码量统计===================================================
EasyClient/EasyServer/Engine1.0 code lines -> 8000+
===================================================
Engine1.0/HttpClient.hpp newadd code lines -> 0361+
Engine1.0/TcpHttpServer.hpp newadd code lines -> 0029+
......@@ -19,6 +20,48 @@ g++ server.cpp -std=c++11 -pthread -o EasyServer
HelloCpp code lines -> 0029+
TestDemo code lines -> 0017+
code lines sum -> 1081+
=======根据gitcode提交统计:
1.windows系统支持ipv6 094+
2.客户端增加ipv6调整 017+
3.服务端升级为ipv6_001 113+
4.windows系统支持ipv6 035+
5.bat批处理启动脚本文件 042+
6.服务端和客户端IOCP网络模型支持IPV6 166+
7.IPV6支持ubuntu 161+
8.完善局域网TCP客户端支持ipv6连接功能 058+
9.IOCP网络模型支持获取新加入客户端IP信息 070+
10.IOCP网络模型支持获取新加入客户端ip 053+
11.服务器将新加入客户端IP信息存储到client对象中 062+
12.windows和linux系统ipv6差异 027+
13.升级日志系统支持临时字符串变量:异步日志系统输出 080+
14.解决方案新增项目:http_server 110+
15.在不同系统下选择最佳网络通信模型 037+
16.简单认识http请求 065+
17.http请求格式解读 050+
18.创建httpclient,并增加判定接收到http完整消息方法 065+
19.函数抽象处理代码冗余,定义tcphttpserver 079+
20.处理bug: 字符串结束标识符添加在正确位置以及预留一字节空间 011+
21.处理http请求消息后正确移除消息 055+
22.处理http网络请求并进行网络应答 028+
23.应答http请求:400_bad 066+
24.解析http客户端请求请求头部分 050+
25.解析http请求消息的请求行部分 065+
26.增加cpp风格解析示例code 087+
27.新增封装分割字符串类splitstring 080+
28.完整解析http get数据请求 100+
29.准确响应http_get请求 115+
30.应答Http客户端简单html页面 040+
31.简易web服务器响应www目录下请求网页 092+
32.封装http应答消息函数 055+
33.简易web服务器对过大文件请求返回404应答 056+
34.web服务器新增:动态配置www目录和index默认页面 140+
35.web简易网络服务器解析http/post网络数据请求1 064+
36.服务器新增:处理http/client发送的连续POST数据请求2 070+
37.解析HTTP/POST请求3 073+
38.HTTP版本功能对比分析 028+
39.增加client的状态并服务器在发送完应答消息后主动关闭连接功能 080+ [2023-10-2: 2739]
code lines sum -> 2739+
//===================================================================
......@@ -352,6 +395,7 @@ http1.0及早期版本:
http客户端进行网络请求,http服务器进行网络应答流程完毕后,http服务器
会主动关闭与这个客户端的连接,属于短连接。只能完成这样的一次的网络消息的数据请求和数据应答就结束。
在1.0版本,http是一个短连接。
默认短连接,但是可以使用keep-alive参数告知服务器要建立一个长链接。
http1.1版本:
支持持久连接(connection: keep-alive),及TCP默认连接不关闭,可以被多个请求复用,超出心跳时间,
......@@ -362,6 +406,7 @@ http服务器才会主动关闭与这个http客户端的连接。
http客户端可以多次请求,但是,是一发一收模式,http客户端进行一次请求后,必须在服务器应答完成后,
http客户端才能继续发起下一次数据请求。
当前主流版本。算是一个长连接,有心跳时间。
默认使用长连接,可有效减少TCP三次握手开销。
http2.0版本:
http客户端可以同时发起多个数据请求,也就是说无需收到第一次请求的应答数据前,http客户端也可以
......@@ -391,8 +436,15 @@ http客户端(采用的正牌浏览器)都会主动关闭与服务器的连接
74.当前新增功能,服务端在发送完应答消息后,主动断开与客户端的连接,仅仅使用select网络
通信模型和epoll网络通信模型,针对iocp网络通信模式后面会专门讲解。
75.http客户端数据请求,每次都会发送请求行,请求头上来。而websocket在http协议之上,
在第一建立连接的时候发送的请求行+请求头,建立握手关系,后面通信就不会发送这部分
数据了,此时对服务器端客户端对象状态的控制需要更加准确。
76.如果http客户端发送的数据请求存在字段[Connection: keep-alive], web
服务器可以建立一个长连接。
77.web服务器支持http长链接和http短连接两种模式,同时http客户端请求头字段
Connection字段处理。
......
Info [2023-9-29 10:59:32]Log::setLogPath success,<ServerLog.txt,w>
Error [2023-9-29 10:59:32]Config::getStr not find <strIP>
Info [2023-9-29 10:59:32]Config::getStr strIP=any
Error [2023-9-29 10:59:32]Config::getStr not find <nPort>
Info [2023-9-29 10:59:32]Config::getInt nPort=4568
Error [2023-9-29 10:59:32]Config::getStr not find <nThread>
Info [2023-9-29 10:59:32]Config::getInt nThread=1
Error [2023-9-29 10:59:32]Config::getStr not find <nSendBuffSize>
Info [2023-9-29 10:59:32]Config::getInt nSendBuffSize=10240
Error [2023-9-29 10:59:32]Config::getStr not find <nRecvBuffSize>
Info [2023-9-29 10:59:32]Config::getInt nRecvBuffSize=8192
Error [2023-9-29 10:59:32]Config::getStr not find <nMaxClient>
Info [2023-9-29 10:59:32]Config::getInt nMaxClient=65535
Info [2023-9-29 10:59:32]-ipv4
Info [2023-9-29 10:59:32]create socket<468> success...
Error [2023-9-29 10:59:32]Config::getStr not find <wwwroot>
Info [2023-9-29 10:59:32]Config::getStr wwwroot=./www
Error [2023-9-29 10:59:32]Config::getStr not find <indexpage>
Info [2023-9-29 10:59:32]Config::getStr indexpage=index.html
Info [2023-9-29 10:59:32]bind port<4568> success...
Info [2023-9-29 10:59:32]listen port<468> success...
Info [2023-9-29 10:59:33]thread<1>,time<1.000321>,socket<468>,Accept<0>,Join<0>,recv<0>,msg<0>
Info [2023-9-29 10:59:34]thread<1>,time<1.000363>,socket<468>,Accept<0>,Join<0>,recv<0>,msg<0>
Info [2023-9-29 10:59:35]thread<1>,time<1.000351>,socket<468>,Accept<0>,Join<0>,recv<0>,msg<0>
Info [2023-9-29 10:59:36]thread<1>,time<1.000832>,socket<468>,Accept<0>,Join<0>,recv<0>,msg<0>
Info [2023-9-29 10:59:37]thread<1>,time<1.000385>,socket<468>,Accept<0>,Join<0>,recv<0>,msg<0>
Info [2023-9-29 10:59:38]thread<1>,time<1.000324>,socket<468>,Accept<0>,Join<0>,recv<0>,msg<0>
Info [2023-9-29 10:59:39]thread<1>,time<1.000316>,socket<468>,Accept<0>,Join<0>,recv<0>,msg<0>
Info [2023-9-29 10:59:40]thread<1>,time<1.000324>,socket<468>,Accept<0>,Join<0>,recv<0>,msg<0>
Info [2023-9-29 10:59:41]thread<1>,time<1.000387>,socket<468>,Accept<0>,Join<0>,recv<0>,msg<0>
Info [2023-9-29 10:59:41]Accept_Ipv4 : 127.0.0.1
Info [2023-9-29 10:59:41]Accept New Client : [ip=127.0.0.1] [cSock=504]
Info [2023-9-29 10:59:49]thread<1>,time<7.992039>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 10:59:49]GET /add?&a=10&b=20 HTTP/1.1
Host: 127.0.0.1:4568
Connection: keep-alive
Cache-Control: max-age=0
sec-ch-ua: "Not-A.Brand";v="24", "Chromium";v="14"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.125 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Info [2023-9-29 10:59:49]Accept_Ipv4 : 127.0.0.1
Info [2023-9-29 10:59:49]Accept New Client : [ip=127.0.0.1] [cSock=516]
Info [2023-9-29 10:59:49]socket[504] OnClose positively.
Info [2023-9-29 10:59:49]~Client[sId=1 id=1 socket=504]
Info [2023-9-29 10:59:49]Client::Destory[sId=1 id=1 socket=504]
Info [2023-9-29 10:59:50]thread<1>,time<1.000353>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 10:59:51]thread<1>,time<1.000386>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 10:59:52]thread<1>,time<1.000343>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 10:59:53]thread<1>,time<1.000342>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 10:59:54]thread<1>,time<1.000350>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 10:59:55]thread<1>,time<1.000324>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000674>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000381>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000320>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000347>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000286>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000321>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000282>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000383>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000325>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000279>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000461>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000294>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000283>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000382>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000334>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000325>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000350>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000380>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000386>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000287>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000965>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000325>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000322>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000321>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000324>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000360>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000381>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000338>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000360>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000343>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000613>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000324>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:28]thread<1>,time<1.000323>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:29]thread<1>,time<1.000323>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:30]thread<1>,time<1.000323>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:31]thread<1>,time<1.000324>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:32]thread<1>,time<1.000342>,socket<468>,Accept<1>,Join<1>,recv<0>,msg<0>
Info [2023-9-29 11:0:32]TcpServer.Close begin
Info [2023-9-29 11:0:32]Server1.Close begin
Info [2023-9-29 11:0:32]Server1.OnRun exit
Info [2023-9-29 11:0:32]~Client[sId=1 id=2 socket=516]
Info [2023-9-29 11:0:32]Client::Destory[sId=1 id=2 socket=516]
Info [2023-9-29 11:0:32]Server1.Close end
Info [2023-9-29 11:0:32]Server1.~Server exit begin
Info [2023-9-29 11:0:32]Server1.Close begin
Info [2023-9-29 11:0:32]Server1.Close end
Info [2023-9-29 11:0:32]Server1.~Server exit end
Info [2023-9-29 11:0:32]TcpServer.Close end
Info [2023-9-29 11:0:32]exit.
Info [2023-9-29 11:0:32]TcpServer.Close begin
Info [2023-9-29 11:0:32]TcpServer.Close end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册