当前位置: 首页 > news >正文

做销售的去哪个网站应聘优化设计数学

做销售的去哪个网站应聘,优化设计数学,门户网站兴化建设局 金,宿迁做网站哪家公司好粘包的产生 当客户端发送多个数据包给服务器时#xff0c;服务器底层的tcp接收缓冲区收到的数据为粘连在一起的。这种情况的产生通常是服务器端处理数据的速率不如客户端的发送速率的情况。比如#xff1a;客户端1s内连续发送了两个hello world#xff01;,服务器过了2s才接…粘包的产生 当客户端发送多个数据包给服务器时服务器底层的tcp接收缓冲区收到的数据为粘连在一起的。这种情况的产生通常是服务器端处理数据的速率不如客户端的发送速率的情况。比如客户端1s内连续发送了两个hello world,服务器过了2s才接收数据那一次性读出两个hello world tcp底层的安全和效率机制不允许字节数特别少的小包发送频率过高tcp会在底层累计数据长度到一定大小才一起发送比如连续发送1字节的数据要累计到多个字节才发送。 粘包处理 处理粘包的方式主要采用应用层定义收发包格式的方式这个过程俗称切包处理常用的协议被称为tlv协议(消息id消息长度消息内容)。 tlv TLVType-Length-Value是一种通信协议用于在通信中传输结构化数据。它将数据分为三个部分类型Type、长度Length和值Value每个部分都以固定的格式进行编码和解码。 但是我下边的格式并不是标准的tlv格式而是采用的lv模式即只包含length和value。 完善消息节点 class MsgNode { public://这里的构造方法主要方便后续调用Send接口构造消息节点MsgNode(char* msg, short data_len) : total_len(data_len HEAD_LENGTH), cur_len(0) {_data new char[total_len 1];memcpy(_data, data_len, HEAD_LENGTH);memcpy(_data HEAD_LENGTH, msg, data_len);_data[total_len] \0;}//这里的构造方法则是用于在进行切包过程中构造处理数据的节点MsgNode(short data_len) :total_len(data_len), cur_len(0) {_data new char[total_len 1];}//Clear方法是用于清理节点的数据避免多次构造析构节点void Clear() {memset(_data, 0, total_len);cur_len 0;}~MsgNode() {delete[] _data;} private:friend class Session;//表示已经处理的数据长度int cur_len;//表示处理数据的总长度int total_len;//表示数据的首地址char* _data; };完善两个构造函数和添加Clear函数 1、第一个构造方法主要方便后续调用Send接口构造消息节点 2、第二个构造方法则是用于在进行切包过程中构造处理数据的节点 3、Clear方法是用于清理节点的数据避免多次构造析构节点 session类完善 _recv_msg_node用于存放收到数据包中的数据 _b_head_parse表示头部是否解析完成 _recv_head_node用于存放接收到数据包中的头部信息 完善hand_read回调函数 void Session::handle_read(const boost::system::error_code ec, size_t bytes_transferred,std::shared_ptrSession self_shared) {if (ec) {std::cout read error, error code: ec.value() read message: ec.message() std::endl;Close();server_-ClearSession(uuid);}else {PrintRecvData(data_, bytes_transferred);std::chrono::milliseconds dura(2000);std::this_thread::sleep_for(dura);//已经移动的字节数int copy_len 0;while (bytes_transferred) {//头部尚未解析完成if (!_b_head_parse) {//收到的数据不足头部大小这种情况很少发生if (bytes_transferred _recv_head_node-cur_len HEAD_LENGTH) {memcpy(_recv_head_node-_data _recv_head_node-cur_len, data_ copy_len, bytes_transferred);_recv_head_node-cur_len bytes_transferred;memset(data_, 0, MAX_LENGTH);sock_.async_read_some(boost::asio::buffer(data_, MAX_LENGTH),std::bind(Session::handle_read, this,std::placeholders::_1, std::placeholders::_2, self_shared));return;}//走到这里说明收到的数据大于头部可能是一个粘连的数据包但是首先需要将头部节点两字节读完//处理头部剩余未复制的长度int head_remain HEAD_LENGTH - _recv_head_node-cur_len;if (head_remain) {memcpy(_recv_head_node-_data _recv_head_node-cur_len, data_ copy_len, head_remain);//更新已处理的数据copy_len head_remain;/** 这里不能更新头部节点的cur_len。* 因为* 1、当一次进来cur_len等于0处理之后的偏移量copy_len就为2* 2、当头部未读取完成后续读取会修正为正确的偏移量但是种情况很少发生* 3、之后的读取头部信息都会发生覆盖*///_recv_head_node-cur_len head_remain;bytes_transferred - head_remain;}//获取头部数据short data_len 0;memcpy(data_len, _recv_head_node-_data, HEAD_LENGTH);std::cout data_len is data_len std::endl;if (data_len MAX_LENGTH) {std::cout invalid data length is data_len std::endl;server_-ClearSession(uuid);return;}//头部节点处理完成就可以开始处理数据域的数据节点_recv_msg_node std::make_sharedMsgNode(data_len);//消息长度小于头部规定长度说明数据未收全则先将消息放到接收节点中if (bytes_transferred data_len) {memcpy(_recv_msg_node-_data _recv_msg_node-cur_len, data_ copy_len, bytes_transferred);_recv_msg_node-cur_len bytes_transferred;memset(data_, 0, MAX_LENGTH);sock_.async_read_some(boost::asio::buffer(data_, MAX_LENGTH),std::bind(Session::handle_read, this,std::placeholders::_1, std::placeholders::_2, self_shared));//表示头部处理完成当下次进来的时候就会直接跳过头部处理环节_b_head_parse true;return;}//走到这里表示消息长度大于头部规定长度这里可能是一个完整包也可能是多个粘连的包memcpy(_recv_msg_node-_data _recv_msg_node-cur_len, data_ copy_len, data_len);_recv_msg_node-cur_len data_len;copy_len data_len;bytes_transferred - data_len;_recv_msg_node-_data[_recv_msg_node-total_len] \0;std::cout receive data is: _recv_msg_node-_data std::endl;//调用send发送给客户端Send(_recv_msg_node-_data, _recv_msg_node-total_len);//继续轮询处理下个未处理的数据重置数据包和头部解析的情况_b_head_parse false;_recv_msg_node-Clear();//说明这不是一个多个粘连的数据包if (bytes_transferred 0) {memset(data_, 0, MAX_LENGTH);sock_.async_read_some(boost::asio::buffer(data_, MAX_LENGTH),std::bind(Session::handle_read, this,std::placeholders::_1, std::placeholders::_2, self_shared));return;}//走到这里说明这就是一个多个粘连的数据包continue;}//走到这里就说明头部是已经解析完成的是处理数据未收全的情况int remain_msg _recv_msg_node-total_len - _recv_msg_node-cur_len;//说明收到的数据仍然不足头部规定大小的情况if (bytes_transferred remain_msg) {memcpy(_recv_msg_node-_data _recv_msg_node-cur_len, data_ copy_len, bytes_transferred);_recv_msg_node-cur_len bytes_transferred;memset(data_, 0, MAX_LENGTH);sock_.async_read_some(boost::asio::buffer(data_, MAX_LENGTH),std::bind(Session::handle_read, this,std::placeholders::_1, std::placeholders::_2, self_shared));return;}//走到这里说明收到的数据是大于等于头部规定大小的接收到的数据可能是个完整的数据包也可能多个粘连的数据包memcpy(_recv_msg_node-_data _recv_msg_node-cur_len, data_ copy_len, remain_msg);_recv_msg_node-cur_len remain_msg;bytes_transferred - remain_msg;copy_len remain_msg;_recv_msg_node-_data[_recv_msg_node-total_len] \0;std::cout receive data is: _recv_msg_node-_data std::endl;//处理完当前数据包的分割后调用send接口向客户端发送回去Send(_recv_msg_node-_data, _recv_msg_node-total_len);//继续轮询处理下个数据包重置接收数据节点和头部解析情况_b_head_parse false;_recv_msg_node-Clear();//说明数据包并不是粘连的if (bytes_transferred 0) {memset(data_, 0, MAX_LENGTH);sock_.async_read_some(boost::asio::buffer(data_, MAX_LENGTH),std::bind(Session::handle_read, this,std::placeholders::_1, std::placeholders::_2, self_shared));return;}//走到这里说明数据包是粘连的continue; }} } 这里hand_read函数的完善逻辑代码比较长其中的注释给的比较详细需要各位仔细读。但是逻辑可能头一两次读可能还是会有些蒙多读几遍可能就会好得多。 这里还是得必要得说一下我们都知道异步读写函数得回调函数中的参数bytes_transferred表示已经读取到的字节数但是我们在这里还是需要对这些已经读到的数据进行处理。其中定义copy_len表示已经处理的字节数bytes_transferred则表示为还未处理的数据尽管已经被读取到了但是还是尚未被处理需要好好理解下。 这里在session类中还定义了两个宏MAX_LENGTH表示数据包的最大长度就是1024*2字节。HEAD_LENGTH表示头部长度就是2字节。 这里我也画了一个逻辑图供大家梳理这里的代码逻辑希望能对大家理解有帮助。 粘包现象的测试 在session类中写一个打印函数在每次触发读事件回调的时候调用下这个函数。这里打印的是tcp缓冲区的数据boost asio从tcp已经是已经做了将tcp缓冲区的数据拿出来的所以这里打印即可。 为了制造粘包现象我们可以让服务器端隔2s处理一次读写而客户端则不停的发送和读取就能制造出粘包现象了。下边是提供的客户端的代码。 #include iostream #include boost/asio.hpp #include thread using namespace std; using namespace boost::asio::ip; const int MAX_LENGTH 1024 * 2; const int HEAD_LENGTH 2; int main() {//测试粘包现象客户端try {//创建上下文服务boost::asio::io_context ioc;//构造endpointtcp::endpoint remote_ep(address::from_string(127.0.0.1), 1234);tcp::socket sock(ioc);boost::system::error_code error boost::asio::error::host_not_found;sock.connect(remote_ep, error);if (error) {cout connect failed, code is error.value() error msg is error.message();return 0;}thread send_thread([sock] {for (;;) {this_thread::sleep_for(std::chrono::milliseconds(2));const char* request hello world!;size_t request_length strlen(request);char send_data[MAX_LENGTH] { 0 };memcpy(send_data, request_length, 2);memcpy(send_data 2, request, request_length);boost::asio::write(sock, boost::asio::buffer(send_data, request_length 2));}});thread recv_thread([sock] {for (;;) {this_thread::sleep_for(std::chrono::milliseconds(2));cout begin to receive... endl;char reply_head[HEAD_LENGTH];size_t reply_length boost::asio::read(sock, boost::asio::buffer(reply_head, HEAD_LENGTH));short msglen 0;memcpy(msglen, reply_head, HEAD_LENGTH);char msg[MAX_LENGTH] { 0 };size_t msg_length boost::asio::read(sock, boost::asio::buffer(msg, msglen));std::cout Reply is: ;std::cout.write(msg, msglen) endl;std::cout Reply len is msglen;std::cout \n;}});send_thread.join();recv_thread.join();}catch (std::exception e) {std::cerr Exception: e.what() endl;}return 0; }现象如下图测试环境Windows visual studio  完整服务端代码codes-C: C学习 - Gitee.com 这里的echo服务器实现了粘包的处理但是在不同的平台下仍存在收发数据异常的问题其根本原因就是平台大小端的差异。
http://www.hkea.cn/news/14527628/

相关文章:

  • 专业做网站公司做网站设计所遇到的问题
  • 建设网站什么费用直接网址登录wordpress
  • 虚拟机中做网站网站系统目前运行稳定
  • 厦门工商网站查询企业信息商业软文怎么写
  • 宁波网站建设营销定制在线外链工具
  • 成都网站建设代理加盟潍坊网站建设方案外包
  • icp备案网站负责人wordpress categories
  • 移动网站建设解决方案衡阳县专业做淘宝网站
  • 英文网站建设怎么样自媒体seo优化
  • 公司都是自己制作网站电子商务网站建设规划实践成果
  • 岳阳企业网站定制开发高职高专 网站建设与维护
  • 开一个网站建设公司需要什么软件app大全
  • php+ajax网站开发典型实例pdfwordpress关键词采集文章
  • 网站优化策略wordpress注册数学验证
  • 网站建设找哪家wordpress 让置顶显示在分类目前
  • 做网站聊城做网站有哪些费用
  • 网站群建设 公司市政道路毕业设计代做网站
  • 中山网站建设最好的公司推荐一下做年会视频的网站
  • 网站建设的初衷获取文章内容 wordpress
  • 大兴黄村网站建设公司免费空间说说赞领取网站
  • 云信智联商丘网站建设建设信用卡激活中心网站
  • 蒙特网站建设公司网站空间上传工具
  • 深圳沙井做公司网站友情链接权重高的网站
  • 苏州网站设计服务做淘宝网站运营工作流程
  • 创美艺佳网站是谁做的百度智能建站系统
  • 山西宏图建设集团有限公司网站郑州网站建设公司如何
  • 合肥建站公司哪韩国食品网站设计欣赏
  • 欧洲做r18 cg的网站齐家网装修公司地址
  • 乡镇做电器网站能不能营运职业生涯规划大赛心得
  • 制作动态表情的网站wordpress网站转移