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

金融公司网站 html台州网页设计

金融公司网站 html,台州网页设计,如何写好网站文案,优质的聊城网站建设目录 前言 1.理解协议 2.网络版本计算器 2.1设计思路 2.2接口设计 2.3代码实现#xff1a; 2.4编译测试 总结 前言 在之前的文章中#xff0c;我们说TCP是面向字节流的#xff0c;但是可能对于面向字节流这个概念#xff0c;其实并不理解的#xff0c;今天我们要介…目录 前言 1.理解协议 2.网络版本计算器 2.1设计思路 2.2接口设计 2.3代码实现 2.4编译测试 总结 前言 在之前的文章中我们说TCP是面向字节流的但是可能对于面向字节流这个概念其实并不理解的今天我们要介绍的是如何理解TCP是面向字节流的通过编码的方式自己定制协议实现序列化和反序列化相信看完这篇文章之后关于TCP面向字节流的这个概念你将会有一个清晰的认识下面我们就一起来看看。 1.理解协议 前面我们通俗的介绍过协议在网络中协议是属于一种约定今天要说的是数据在网络中传输的时候协议又是如何体现的。 根据我们之前写的TCP服务器实现数据通信知道socket api的接口, 在读写数据时, 都是按 字符串 的方式来发送接收的. 如果我们要传输一些结构化的数据 怎么办呢? 什么是结构化的数据呢 举个简单的例子比如在微信上发送信息的时候除了有发送的信息之外还包含有昵称时间头像这些信息这些合起来就称为是结构化的数据。 所以我们将结构化的数据打包形成一个字符串的过程就称为是序列化将打包形成的一个字符串转化为结构化数据的过程就称为是反序列化 如图所示 TCP发送和接受数据的流程 如图所示 作为程序员在应用层定义一个缓冲区然后send接口将数据发送在这里发送不是将数据直接发送到网络里了而是调用send接口将数据拷贝到传输层操作系统维护的缓冲区中而read是将传输层的数据拷贝到应用层当数据拷贝到传输层之后剩下数据如何继续发送是由操作系统进行维护的所以将TCP协议称为是传输控制协议又因为TCP协议既可以是客户端向服务端发送信息也可以是服务端向客户端发送信息所以TCP是全双工的。 了解了TCP协议发送和接受数据的流程之后因为TCP是面向字节流的思考当数据由客户端发送给服务端的时候有没有可能服务端的接受缓冲区中不足一个报文有没有可能上层来不及处理导致服务端传输层接受缓冲区中有多个报文的情况此时如何正确的拿到一个完整的报文呢 因为这些问题的存在所以我们要定制协议明确一个完整报文大小明确一个报文和一个报文的边界所以我们要采取定制协议的方案获取到一个正确的报文。 一般采取的策略有三种 1.定长 2.特殊符号 3.自描述的方式 下面我们按照上述的三种方式实现编码上的协议定制。 2.网络版本计算器 说明为了演示协议定制和序列化以及反序列化在编码上如何实现以及如何在编码上体现TCP面向字节流的特性我们通过实现一个网络版本计算器为大家进行介绍 实现网络版本计算机约定 客户端发送一个形如11的字符串; 这个字符串中有两个操作数, 都是整形; 两个数字之间会有一个字符是运算符, 运算符只能是 ; 数字和运算符之间没有空格 2.1设计思路 客户端将想要计算的请求按照序列化的方式打包成一个字符串然后发送给服务端服务端按照定制协议的方式准确收到客户端的请求然后服务端进行反序列化获取到结构化的数据然后进行处理业务逻辑计算结果结果计算完成之后服务端将计算结果序列化打包形成一个字符串发送给客户端然后客户端按照定制协议的方式准确获取到服务端发送过来的一个完整报文至此就基于TCP协议实现了一个网络版本的计算器 2.2接口设计 要向完成上述的要求就必须要包含几个接口 a.请求的序列化和反序列化 b.响应的序列化和反序列化 c.协议定制 d.计算业务逻辑 e.准确获取一个报文 f.客户端和服务端编写 2.3代码实现 1.请求的序列化和反序列化 class Request { public:Request():x(0),y(0),op(char()){}Request(int x_, int y_, char op_) : x(x_), y(y_), op(op_){}bool serialize(std::string *out){*out ;// 结构化 - x op y;std::string x_string std::to_string(x);std::string y_string std::to_string(y);*out x_string;*out SEP;*out op;*out SEP;*out y_string;return true;}// x op yyyy;bool deserialize(const std::string in){// x op y - 结构化auto left in.find(SEP);auto right in.rfind(SEP);if (left std::string::npos || right std::string::npos)return false;if (left right)return false;if (right - (left SEP_LEN) ! 1)return false;std::string x_string in.substr(0, left); // [0, 2) [start, end) , start, end - startstd::string y_string in.substr(right SEP_LEN);if (x_string.empty())return false;if (y_string.empty())return false;x stoi(x_string);y stoi(y_string);op in[left SEP_LEN];return true;}public:int x;int y;char op; }; 序列化结果将x,y,op - 转化为 x y op\r\n 反序列化结果x y op\r\n - 转化为 x,y,op 2.响应的序列化和反序列化 #define SEP #define SEP_LEN strlen(SEP) // 不敢使用sizeof() #define LINE_SEP \r\n #define LINE_SEP_LEN strlen(LINE_SEP) // 不敢使用sizeof() class Response { public:Response():exitcode(0),result(0) {}Response(int exitcode_, int result_) : exitcode(exitcode_), result(result_){}bool serialize(std::string *out){*out ;std::string ec_string std::to_string(exitcode);std::string res_string std::to_string(result);*out ec_string;*out SEP;*out res_string;return true;}bool deserialize(const std::string in){// exitcode resultauto mid in.find(SEP);if (mid std::string::npos)return false;std::string ec_string in.substr(0, mid);std::string res_string in.substr(mid SEP_LEN);if (ec_string.empty() || res_string.empty())return false;exitcode std::stoi(ec_string);result std::stoi(res_string);return true;} public:int exitcode;int result; }; 序列化结果将exitcode,result - 转化为 exitcode result\r\n 反序列化结果 exitcode result\r\n - 转化为 exitcode,result 3.协议定制 说明采用自描述的方式特殊符号给一个报文头部加上报文的长度特殊符号\r\n用来区分报文长度和报文数据 #define SEP #define SEP_LEN strlen(SEP) // 不敢使用sizeof() #define LINE_SEP \r\n #define LINE_SEP_LEN strlen(LINE_SEP) // 不敢使用sizeof() //enLength 和 deLength打包和解包解决服务端和客户端准确拿到数据 // x op y - content_len\r\nx op y\r\n // exitcode result - content_len\r\nexitcode result\r\n std::string enLength(const std::string text) {std::string send_string std::to_string(text.size());send_string LINE_SEP;send_string text;send_string LINE_SEP;return send_string; }// content_len\r\nexitcode result\r\n bool deLength(const std::string package, std::string *text) {auto pos package.find(LINE_SEP);if (pos std::string::npos)return false;std::string text_len_string package.substr(0, pos);int text_len std::stoi(text_len_string);*text package.substr(pos LINE_SEP_LEN, text_len);return true; } 4.计算业务逻辑 //req是反序列化后的结果根据res业务处理填充req即可 bool cal(const Request req,Response res) {//req是结构化的数据,可以直接使用// req已经有结构化完成的数据啦你可以直接使用res.exitcode OK;res.result OK;switch (req.op){case :res.result req.x req.y;break;case -:res.result req.x - req.y;break;case *:res.result req.x * req.y;break;case /:{if (req.y 0)res.exitcode DIV_ZERO;elseres.result req.x / req.y;}break;case %:{if (req.y 0)res.exitcode MOD_ZERO;elseres.result req.x % req.y;}break;default:res.exitcode OP_ERROR;break;}return true; } 5.准确获取一个报文 //从sock中读取数据保存到text中 //continue是因为tcp协议是面向字节流的传输数据的时候可能不完整 bool recvPackage(int sock,string inbuffer,string *text) {char buffer[1024];while (true){ssize_t n recv(sock, buffer, sizeof(buffer) - 1, 0);if (n 0){buffer[n] 0;inbuffer buffer;// 分析处理auto pos inbuffer.find(LINE_SEP);if (pos std::string::npos)continue;std::string text_len_string inbuffer.substr(0, pos);int text_len std::stoi(text_len_string);int total_len text_len_string.size() 2 * LINE_SEP_LEN text_len;// text_len_string \r\n text \r\n inbuffer.size();std::cout 处理前#inbuffer: \n inbuffer std::endl;if (inbuffer.size() total_len){std::cout 你输入的消息没有严格遵守我们的协议正在等待后续的内容, continue std::endl;continue;}// 至少有一个完整的报文*text inbuffer.substr(0, total_len);inbuffer.erase(0, total_len);std::cout 处理后#inbuffer:\n inbuffer std::endl;break;}elsereturn false;}return true; } 注看到这里我们就可以理解了TCP是面向字节流的概念了。 6.客户端和服务端实现 calServer.hpp: #pragma once#include iostream #include string #include cstring #include cstdlib #include functional #include unistd.h #include sys/types.h #include sys/socket.h #include netinet/in.h #include arpa/inet.h #include sys/wait.h #include signal.h #include log.hpp #include protocol.hpp //按照协议约定读取请求 using namespace std; namespace server {enum{USAGE_ERR 1,SOCKET_ERR,BIND_ERR,LISTEN_ERR};static const uint16_t gport 8080;static const int gbacklog 5;typedef functionbool(const Request req,Response res) func_t;//读取请求保证解耦void handlerEnter(int sock,func_t fun){string inbuffer;while(true){//1. 读取content_len\r\nx op y\r\n// 1.1 你怎么保证你读到的消息是 【一个】完整的请求string req_text, req_str;if (!recvPackage(sock,inbuffer,req_text))return;std::cout 带报头的请求\n req_text std::endl;//req_str:获取报文if (!deLength(req_text, req_str))return;std::cout 去掉报头的正文\n req_str std::endl;// 2. 对请求Request反序列化// 2.1 得到一个结构化的请求对象Request req;if(!req.deserialize(req_str))return;// 3. 计算机处理req.x, req.op, req.y --- 业务逻辑// 3.1 得到一个结构化的响应Response res;fun(req,res);//req处理的结果放到res中,采用回调的方式保证上层业务逻辑和服务器的解耦// 4.对响应Response进行序列化// 4.1 得到了一个字符串string resp_str;if(!res.serialize(resp_str))return;std::cout 计算完成, 序列化响应: resp_str std::endl;// 5. 然后我们在发送响应// 5.1 构建成为一个完整的报文std::string send_string enLength(resp_str);std::cout 构建完成完整的响应\n send_string std::endl;send(sock, send_string.c_str(), send_string.size(), 0); // 其实这里的发送也是有问题的不过后面再说}}class CalServer{public:CalServer(const uint16_t port gport) : _listensock(-1), _port(port){}void initServer(){// 1. 创建socket文件套接字对象_listensock socket(AF_INET, SOCK_STREAM, 0);if (_listensock 0){logMessage(FATAL, create socket error);exit(SOCKET_ERR);}logMessage(NORMAL, create socket success: %d, _listensock);// 2. bind绑定自己的网络信息struct sockaddr_in local;memset(local, 0, sizeof(local));local.sin_family AF_INET;local.sin_port htons(_port);local.sin_addr.s_addr INADDR_ANY;if (bind(_listensock, (struct sockaddr *)local, sizeof(local)) 0){logMessage(FATAL, bind socket error);exit(BIND_ERR);}logMessage(NORMAL, bind socket success);// 3. 设置socket 为监听状态if (listen(_listensock, gbacklog) 0) // 第二个参数backlog后面在填这个坑{logMessage(FATAL, listen socket error);exit(LISTEN_ERR);}logMessage(NORMAL, listen socket success);}void start(func_t fun){for (;;){// 4. server 获取新链接// sock, 和client进行通信的fdstruct sockaddr_in peer;socklen_t len sizeof(peer);int sock accept(_listensock, (struct sockaddr *)peer, len);if (sock 0){logMessage(ERROR, accept error, next);continue;}logMessage(NORMAL, accept a new link success, get new sock: %d, sock); // ?// version 2 多进程版(2)pid_t id fork();if (id 0) // child{close(_listensock);handlerEnter(sock,fun);close(sock);exit(0);}close(sock);// fatherpid_t ret waitpid(id, nullptr, 0);if (ret 0){logMessage(NORMAL, wait child success); // ?}}}~CalServer() {}private:int _listensock; // 不是用来进行数据通信的它是用来监听链接到来获取新链接的uint16_t _port;};} // namespace server calClient.hpp #pragma once#include iostream #include string #include cstring #include sys/types.h #include sys/socket.h #include netinet/in.h #include arpa/inet.h #include unistd.h #include protocol.hpp#define NUM 1024class CalClient { public:CalClient(const std::string serverip, const uint16_t serverport): _sock(-1), _serverip(serverip), _serverport(serverport){}void initClient(){// 1. 创建socket_sock socket(AF_INET, SOCK_STREAM, 0);if (_sock 0){std::cerr socket create error std::endl;exit(2);}}void start(){struct sockaddr_in server;memset(server, 0, sizeof(server));server.sin_family AF_INET;server.sin_port htons(_serverport);server.sin_addr.s_addr inet_addr(_serverip.c_str());if (connect(_sock, (struct sockaddr *)server, sizeof(server)) ! 0){std::cerr socket connect error std::endl;}else{std::string line;std::string inbuffer;while (true){std::cout mycal ;std::getline(std::cin, line); // 11Request req ParseLine(line); // 11std::string content;req.serialize(content);std::string send_string enLength(content);send(_sock, send_string.c_str(), send_string.size(), 0); // bug?? 不管std::string package, text;// content_len\r\nexitcode result\r\nif (!recvPackage(_sock, inbuffer, package))continue;if (!deLength(package, text))continue;// exitcode resultResponse resp;resp.deserialize(text);std::cout exitCode: resp.exitcode std::endl;std::cout result: resp.result std::endl;}}}Request ParseLine(const std::string line){// 建议版本的状态机//11 123*456 12/0int status 0; // 0:操作符之前1:碰到了操作符 2:操作符之后int i 0;int cnt line.size();std::string left, right;char op;while (i cnt){switch (status){case 0:{if(!isdigit(line[i])){op line[i];status 1;}else left.push_back(line[i]);}break;case 1:i;status 2;break;case 2:right.push_back(line[i]);break;}}std::cout std::stoi(left) std::stoi(right) op std::endl;return Request(std::stoi(left), std::stoi(right), op);}~CalClient(){if (_sock 0)close(_sock);}private:int _sock;std::string _serverip;uint16_t _serverport; }; 2.4编译测试 如图所示我们准确的实现了网络版本计算器 总结 通过上面代码的编写包含定制协议序列化和反序列代码的实现我们就能够理解协议在网络传输的重要性了以及理解了TCP是面向字节流的概念。感谢大家的观看希望能够帮助到大家我们下次再见。
http://www.tj-hxxt.cn/news/140662.html

相关文章:

  • 智能家居型网站开发网络营销推广的心得体会
  • 网站建设广州网站建设简单的电商网站
  • 在旅行社做网站运营静态网站开发的目的
  • 做app网站的软件有哪些内容吗cent os wordpress
  • 河南城乡住房和建设厅网站开发公司装饰装修合同范本简单
  • 南京做网站南京乐识赞网页美工设计图片
  • node 网站开发wordpress瀏覽器圖標
  • 雄安网站建设推广海南旅游网站开发背景
  • 做一个网站策划上传网站怎么安装
  • 站长工具查询入口大型企业网站源码
  • asp网站的缺点怎样在百度上发表文章
  • node.js企业网站开发旅行社网站制作
  • 网站降权查下设计模板网站都有哪些
  • 网站的模板家谱网站怎么做
  • 服务器建立网站c++线上培训机构哪个好
  • 做注册任务的网站有哪些郑州做网站哪家最好
  • 网站建设注册密码咋弄国际域名注册网站
  • 四川省网站建设网站开发怎样
  • 留言网站怎么做网页设计与制作报告书
  • 怎样找回网站备案密码广东快速做网站公司
  • 合肥网站开发培训学校wordpress弹窗视频播放插件
  • 个人电脑做服务器网站中天建设第四网站
  • 谷歌搜索入口365贵阳哪家网站做优化排名最好
  • 手机什么app做网站湖南禹班建设集团网站
  • 网站的新闻栏与产品栏如何做办公用品网站建设策划书
  • 温室网站建设什么是网站建设策划
  • 深圳建站网站模板河北省住建和城乡建设厅网站
  • 佛山网站建设 骏域网站网站建设备案优化之看
  • 北京网站外包公司营销型网站建设原则
  • 网站建设子栏目文案保定市做网站