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

设计logo网站免费横屏纯色建筑培训机构

设计logo网站免费横屏纯色,建筑培训机构,郑州做网站最好的公司,黑龙江省领导名单目录 一、什么是协议#xff1f; 二、为什么需要有协议呢#xff1f; 三、协议的应用 四、序列化与反序列化的引入 什么是序列化和反序列化#xff1f; 为什么需要序列化和反序列化#xff1f; 五、序列化推荐格式之一#xff1a;JSON介绍 六、网络版计算器编程逻…目录 一、什么是协议 二、为什么需要有协议呢 三、协议的应用 四、序列化与反序列化的引入 什么是序列化和反序列化 为什么需要序列化和反序列化 五、序列化推荐格式之一JSON介绍 六、网络版计算器编程逻辑 本文所涉及到的两种设计模式 工厂模式简单工厂模式、工厂方法模式、抽象工厂模式-CSDN博客 模板方法模式-CSDN博客 一、什么是协议 在日常生活中我们无时无刻不在遵守着“协议”。例如当你点外卖时你提前告知骑手要把外卖放在小区的5号外卖柜中。当外卖平台给你发送“订单已送达”信息后你会前往5号外卖柜取出你的外卖。为什么不去6号外卖柜取走你的外卖呢因为你和骑手已经事先约定好将外卖放在5号外卖柜中这就是你和该名骑手间事先约定好的“协议”双方必须同时遵守这一规则这样才能保证资源处理的正确性。 协议Protocol在计算机科学和通信领域中指的是一组规则或标准用于规定数据如何在不同的系统、设备或进程之间进行交换和处理。协议定义了通信过程中的语法、语义、同步规则以及可能出现的错误处理方式。通过遵循相同的协议不同的硬件、软件或网络系统能够相互理解和协作从而实现信息的有效传输和处理。 二、为什么需要有协议呢 无论是日常生活还是计算机系统、网络通信中协议的存在都是至关重要的。它们为不同主体之间的交互提供了规则和标准确保了沟通和操作的有效性、可靠性以及一致性。无论是人与人之间的交流还是系统与系统之间的通信都需要一套共同的语言或规则。协议就像是一种“共同的语言”确保各方能够理解彼此并按照预定的方式行动。 日常生活例子当你打电话订餐时你和餐厅服务员之间遵循着一种“协议”——你告诉他你想吃什么他确认并记录你的订单。如果每个人点餐时都使用不同的方式或语言沟通就会混乱不堪订单可能会出错。 技术例子在互联网中设备和服务器之间通过HTTP协议进行通信。HTTP定义了请求和响应的格式确保浏览器和服务器能够互相理解并交换信息。如果没有HTTP协议浏览器可能无法正确解释服务器发送的内容。 三、协议的应用 在之前所学的TCP通信中客户端与服务端之间的信息传输是面向字节流的。这就意味着无论是客户端还是服务端我们都需要从套接字中读取完整的请求并对该请求进行处理做出相应的应答。但我们真的能保证每次所读取到的数据都是一个完整的请求吗当客户端一直向服务端发送请求时服务端一直在接收来自客户端的请求信息我们如何保证每次从字节流中提取的一定是一个完整的请求呢——协议 我们事先约定好客户端的每个请求信息和服务端的应答信息遵守如下格式 请求/应答报文“len\r\nInformationStr\r\n” 我们将上述字符串称之为报文其中 len请求字符串的长度字符串形式。 \r\n分隔符字符串用于分隔请求信息和标识一段完整报文的结尾。 InformationStr请求/应答信息字符串形式。 当我们约定好请求与应答信息都要遵守上述格式后那么对于以后客户端/服务端当我们需要从字节流中提取到一个完整的报文信息时我们需要做以下工作来判断当前字节流中是否包含至少一个完整的报文 1、因为当第一次开始处理字节流时字节流的起始端一定是包含len或len字符串的一部分。所以我们首先找到分隔符的位置将len提取出来转化为整数。如果没找到则返回上层继续接收客户端传来的信息。 2、当我们得到信息的长度为len后开始计算该条完整报文的理论长度。如果报文小于理论长度返回上层继续接收信息。否则则说明当前字节流中包含至少一条完整的报文。 3、依据已经得到的InformationStr的起始位置和InformationStr的长度len将报文中的有效信息部分提取出来。并从现有字节流中删除此次提取的完整的报文包括分隔符。 经过上述操作我们就完成了一次对报文的提取工作。 四、序列化与反序列化的引入 什么是序列化和反序列化 序列化Serialization和反序列化Deserialization是计算机科学中用于将数据结构、对象状态或数据内容转换为可以存储或传输的格式的过程。具体来说 序列化是将对象、数据结构或数据转换为字节流或某种特定格式的过程以便于存储到文件、数据库或通过网络传输。序列化后的数据通常是连续的字节流能够被传输或存储。 反序列化是将序列化后的字节流或格式化数据还原为原始对象或数据结构的过程使得应用程序可以重新使用这些数据。 为什么需要序列化和反序列化 当我们在进行网络通信时发送的信息可能不单纯是一个字符串还可能是一个结构体/对象。而对于不同的主机而言由于不同操作系统、编程语言和硬件架构对内存布局和数据类型的处理方式可能不同直接将结构体以字节流的形式传输会面临以下几个问题 字节序Endianness         不同的硬件架构可能使用不同的字节序大端序或小端序来存储整数和浮点数。如果发送方和接收方的字节序不一致直接传输字节流会导致数据解析错误。 内存对齐Memory Alignment         不同平台和编译器可能有不同的内存对齐规则。例如某些平台要求整数必须存储在4字节对齐的地址上而另一些平台可能没有这样的要求。这会导致结构体在不同平台上占用不同大小的内存。 数据类型大小         不同的操作系统和编译器对数据类型如int、float、double等的定义可能不同。例如一个int在32位系统上占4字节在16位系统上可能占2字节。直接传输结构体可能导致数据解析错误。 结构体成员顺序         结构体的成员顺序在不同的平台上可能有所不同。例如某些编译器可能会根据对齐规则重新排列结构体的成员导致相同结构的成员在内存中的顺序不同。 这就意味着我们无法将一个结构体以字节流的形式进行网络通信时的信息的传输因为这可能面临着不可预知的错误因此序列化与反序列化就成为了客户端与服务端之间正确通信的必要步骤。 五、序列化推荐格式之一JSON介绍 JSON是一种轻量级的数据交换格式。它基于JavaScript编程语言的一个子集但独立于语言因此许多现代编程语言都提供了对JSON的支持。 JSON的定义与特点 JSON是一种文本格式的结构化数据序列化方式用于数据交换和存储。它具有简洁、易读、易写的特点同时也易于机器解析和生成。JSON是完全独立于语言的这意味着它可以在不同的编程语言之间轻松传递数据。 JSON的数据类型 JSON支持多种数据类型包括字符串string、数值number、布尔值boolean、对象object、数组array以及null。 字符串由双引号包围的文本。数值可以是整数或浮点数不支持八进制和十六进制。布尔值true或false。对象由花括号{}包围包含零个或多个“键值对”的集合。数组由方括号[]包围包含零个或多个值的有序集合。 解析与生成JSON 解析JSON当接收到JSON格式的数据时应用程序需要将其解析为内部可操作的数据结构如对象、数组等。大多数编程语言都提供了JSON解析库或内置功能来支持这一过程。生成JSON与解析相反生成过程是将程序内部的数据结构转换为JSON格式的字符串以便在网络传输或文件存储中使用。同样地各种编程语言也提供了相应的库或方法来支持这一操作。 在C中引入了jsoncpp。jsoncpp 是一个用于处理 JSON 数据的 C 库。它提供了一种简单的方式来解析、生成、操作和查询 JSON 数据。其应用见如下文章此处不再过多赘述。 Jsoncpp使用简介-CSDN博客 六、网络版计算器编程逻辑 Socket.hpp 对套接字进行封装 #pragma once #include iostream #include cstring #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 pthread.h #include memory#include Log.hpp #include InternetAddr.hppconst static int gblcklog 8;class Socket; // 先声明 using SockSPtr std::shared_ptrSocket; // 智能指针类型别名// 模版方法模式 // 基类提供纯虚函数方法子类需要根据需求设计方法的具体实现 class Socket { public:virtual void CreateSocketOrDie() 0;virtual void CreateBindOrDie(uint16_t port) 0;virtual void CreateListenOrDie(int backlog gblcklog) 0;virtual SockSPtr Accepter(InetAddr *cliaddr) 0;virtual bool Conntecor(const std::string peerip, uint16_t peerport) 0;virtual int Sockfd() 0;virtual void Close() 0;virtual ssize_t Recv(std::string *out) 0;virtual ssize_t Send(const std::string in) 0;public:void BuildListenSocket(uint16_t port){CreateSocketOrDie();CreateBindOrDie(port);CreateListenOrDie();}bool BuildClientSocket(const std::string peerip, uint16_t peerport){CreateSocketOrDie();return Conntecor(peerip, peerport);}// void BuildUdpSocket()// {} };class Tcp_Socket : public Socket { private:int _sockfd;public:Tcp_Socket(int sockfd -1): _sockfd(sockfd){}~Tcp_Socket(){}void CreateSocketOrDie() override{// 1、 创建套接字_sockfd ::socket(AF_INET, SOCK_STREAM, 0);if (_sockfd 0){LOG(FATAL, Sockfd Create False!\n);exit(-1);}LOG(INFO, Sockfd Create Success!\n);}void CreateBindOrDie(uint16_t port) override{struct sockaddr_in local_addr;memset(local_addr, 0, sizeof(local_addr));local_addr.sin_addr.s_addr INADDR_ANY;local_addr.sin_port htons(port);local_addr.sin_family AF_INET;// 2、绑定本地ip地址和port端口号if (::bind(_sockfd, (struct sockaddr *)local_addr, sizeof(local_addr)) 0){LOG(FATAL, Listen Sockfd Bind False!\n);exit(-1);}LOG(INFO, Listen Sockfd Bind Success!\n);}void CreateListenOrDie(int backlog) override{// 3、将套接字设置为【监听状态】 以监听来自客户端的连接请求if (::listen(_sockfd, backlog) 0){LOG(FATAL, Listen Sockfd Listen False!\n);exit(-1);}LOG(INFO, Listen Sockfd Listen Success!\n);}SockSPtr Accepter(InetAddr *client_addr) override{// 1、获取来自客户端的连接请求并获得I/O专用套接字struct sockaddr_in from_client;socklen_t addr_len sizeof(from_client);memset(from_client, 0, addr_len);int _io_sockfd accept(_sockfd, (struct sockaddr *)from_client, addr_len);if (_io_sockfd 0){LOG(FATAL, Server Sockfd Accept False!);return nullptr;}LOG(DEBUG, Server Sockfd Accept Success!);*client_addr from_client;return std::make_sharedTcp_Socket(_io_sockfd);}bool Conntecor(const std::string peerip, uint16_t peerport) override{// 连接服务端struct sockaddr_in to_server;memset(to_server, 0, sizeof(to_server));inet_pton(AF_INET, peerip.c_str(), to_server.sin_addr);to_server.sin_family AF_INET;to_server.sin_port htons(peerport);if (connect(_sockfd, (struct sockaddr *)to_server, sizeof(to_server)) 0){return false;}return true;}int Sockfd() override{ return _sockfd;}void Close() override{if (_sockfd 0){::close(_sockfd);}}ssize_t Recv(std::string *out) override{char inbuffer[4096];ssize_t n ::recv(_sockfd, inbuffer, sizeof(inbuffer) - 1, 0);if (n 0){inbuffer[n] 0;*out inbuffer;}return n;}ssize_t Send(const std::string in) override{return ::send(_sockfd, in.c_str(), in.size(), 0);} }; Protocol.hpp : 协议头文件其中约定了报文格式、请求格式、应答格式、序列化与反序列化方法。 #pragma once #include memory #include string #include jsoncpp/json/json.h #include Log.hpp #include iostream #include cstring // version1 报文“len\r\njson串\r\n” // version2 自定义序列串报文len\r\nx#operator#y\r\n // 分隔字符串 static const std::string separate_str \r\n; static const std::string self_cut_str #; // 网络计算器// 添加报头 std::string AddCode(const std::string json_str) {int len json_str.size();std::string len_str std::to_string(len);return len_str separate_str json_str separate_str; }// 传递进来的报文可能有以下形式。如果报文不完整返回空串到上层让上层继续接收来自客户端的信息。如果能提取到完整json串在传入报文的基础上将json串拆分出来。 // 不能带const // le // len // len\r\n // len\r\n{json}\r\n (] // len\r\n{j // len\r\n{json}\r\nlen\r\n{ // len\r\n{json}\r\n // len\r\n{json}\r\nlen\r\n{json}\r\nlen\r\n{json}\r\nlen\r\n{json}\r std::string RemoveCode(std::string message) // 移除报头返回提取到的json串 {auto _pos message.find(separate_str); // 先找到分隔符的位置if (_pos std::string::npos) // 没找到则返回上层继续接收客户端传来的信息{return std::string();}std::string json_len_str message.substr(0, _pos); // 提取出报文首部json串的长度int json_len stoi(json_len_str);int _total json_len separate_str.size() * 2 json_len_str.size(); // 计算报文理论长度if (message.size() _total) // 如果报文小于理论长度返回上层继续接收信息{return std::string();}std::string ret_json_str message.substr(_pos separate_str.size(), json_len); // 提取报文中的json串message.erase(0, _total); // 在传入报文中删除已经提取的该段报文return ret_json_str; // 返回提取的json串 }// 客户端发起请求 class Request { public:Request(int x -1, int y -1, char oper -1): _x(x), _y(y), _operator(oper){}// 序列化结构体成员 -》 json串bool Serialize(std::string *out_jsonstr){ #ifdef FLAG*out_jsonstr std::to_string(_x) self_cut_str _operator self_cut_str std::to_string(_y);return true; #elseJson::Value root;root[x] _x;root[y] _y;root[operator] _operator;Json::FastWriter writer;*out_jsonstr writer.write(root);return true; #endif}// 反序列化json串 -》 结构体成员bool DeSerialize(const std::string in_jsonstr){#ifdef FLAGauto x_pos in_jsonstr.find(self_cut_str);if(x_pos std::string::npos) return false;auto y_pos in_jsonstr.rfind(self_cut_str);if(y_pos std::string::npos) return false;if(x_pos 1 self_cut_str.size() ! y_pos) return false;_x std::stoi(in_jsonstr.substr(0, x_pos));_y std::stoi(in_jsonstr.substr(y_pos self_cut_str.size()));_operator in_jsonstr[y_pos - 1];return true; #elseJson::Value root;Json::Reader reader;bool res reader.parse(in_jsonstr, root);_x root[x].asInt();_y root[y].asInt();_operator root[operator].asInt();return res; #endif}int X(){return _x;}int Y(){return _y;}char Oper(){return _operator;}void SetValue(int x, int y, char oper){_x x;_y y;_operator oper;}private:int _x; // 左操作数int _y; // 右操作数char _operator; // 运算符 };// 服务端返回应答 class Response { public:Response(int result -1, int exit_code 0, std::string exit_info Success): _result(result), _exit_code(exit_code), _exit_info(exit_info){}// 序列化结构体成员 -》 json串bool Serialize(std::string *out_jsonstr){ #ifdef FLAG*out_jsonstr std::to_string(_result) self_cut_str std::to_string(_exit_code) self_cut_str _exit_info;return true; #elseJson::Value root;root[result] _result;root[exit_code] _exit_code;root[exit_info] _exit_info;Json::FastWriter writer;*out_jsonstr writer.write(root);return true; #endif}// version2 自定义序列串报文len\r\nresult#exit_code#info\r\n// 反序列化json串 -》 结构体成员bool DeSerialize(const std::string in_jsonstr){ #ifdef FLAGauto left in_jsonstr.find(self_cut_str);if(left std::string::npos) return false;auto right in_jsonstr.rfind(self_cut_str);if(right std::string::npos) return false;if(left 1 self_cut_str.size() ! right) return false;_result std::stoi(in_jsonstr.substr(0, left));_exit_code in_jsonstr[right - 1] -\0;_exit_info in_jsonstr.substr(right self_cut_str.size());return true; #elseJson::Value root;Json::Reader reader;bool res reader.parse(in_jsonstr, root);_result root[result].asInt();_exit_code root[exit_code].asInt();_exit_info root[exit_info].asString();return res; #endif}void PrintResult(){std::cout result: _result , code: _exit_code , desc: _exit_info std::endl;}public:int _result; // 计算结果int _exit_code; // 退出码std::string _exit_info; // 退出码对应的退出信息 };// 工厂模式提供构造对象实例的函数方法 class FactoryForRequestAndReponse { public:static std::shared_ptrRequest BulidRequestObject(){return std::make_sharedRequest();}static std::shared_ptrResponse BulidResponseObject(){return std::make_sharedResponse();} }; NetCol.hpp : 计算器头文件其中提供了将请求对象转化为应答对象的方法。 #pragma once#include Protocol.hpp #include memoryclass NetCal { public:std::shared_ptrResponse Calculator(std::shared_ptrRequest req){auto resp FactoryForRequestAndReponse::BulidResponseObject();switch (req-Oper()){case :resp-_result req-X() req-Y();break;case -:resp-_result req-X() - req-Y();break;case *:resp-_result req-X() * req-Y();break;case /:{if (req-Y() 0){resp-_exit_code 1;resp-_exit_info div zero;}else{resp-_result req-X() / req-Y();}}break;case %:{if (req-Y() 0){resp-_exit_code 2;resp-_exit_info mod zero;}else{resp-_result req-X() % req-Y();}}break;default:{resp-_exit_code 3;resp-_exit_info illegal operation;}break;}return resp;} }; Service.hpp : I/O服务类其中包含了服务端进行网络通信的方法。作为服务端类的参数构造服务器对象目的是实现服务器自身启动功能与通信功能方法的解耦。通过传递不同的参数可以使服务器具有对通信信息不同的处理能力。 #pragma once #include NetCol.hpp #include Protocol.hpp #include Socket.hpp #include functional// 服务端需要的任务函数的类型 // using Tcp_Server_FuncType std::functionvoid(SockSPtr, InetAddr); // 注InetAddr 为类该对象中包含目标端的IP地址、端口号// IO_Service 类用于处理服务端对客户端信息的接收和应答工作 内部由外层提供 将 请求 转变为 应答 的功能函数 using Process_Request_and_Return_Response_t std::functionstd::shared_ptrResponse(std::shared_ptrRequest);class IO_Service { private:Process_Request_and_Return_Response_t _process;public:IO_Service(Process_Request_and_Return_Response_t process): _process(process){}void IOExecute(SockSPtr io_socksptr, InetAddr from_client_inetaddr){std::string message;while (true){// 1、接收来自客户端的请求报文if(io_socksptr-Recv(message) 0){LOG(FATAL, Recv fail!);}// 2、将接收到的请求进行解码操作获取json串std::string json_str RemoveCode(message);// 如果没有提取到完整的json串说明服务端当前接收到的报文不完整继续进行recv操作if(json_str.empty()){continue;}std::cout json_str std::endl; // 3、将json串反序列化为请求std::shared_ptrRequest request std::make_sharedRequest();if(!request-DeSerialize(json_str)){LOG(FATAL, request-DeSerialize fail!);}// 4、处理请求返回应答结果构建应答接收应答结果std::shared_ptrResponse response _process(request);// 5、将应答进行序列化std::string return_json_str;if(!response-Serialize(return_json_str)){LOG(FATAL, response-Serialize fail!);}// 将已经序列化的应答做成完整报文发送给客户端// 1、对应答序列化后的json串加码return_json_str AddCode(return_json_str);// 2、将报文发送给客户端if(io_socksptr-Send(return_json_str) 0){LOG(FATAL, Send fail!);}}} }; TCP_Server.hpp服务端类 #pragma once #include sys/types.h #include sys/socket.h #include unistd.h #include string #include iostream #include arpa/inet.h #include cstring #include signal.h #include sys/wait.h #include ThreadPool.hpp #include functional #include Socket.hppstatic uint16_t gport 8888;static const int MAX_LEN 5; static const int BUFFER_SIZE 256;using Tcp_Server_FuncType std::functionvoid(SockSPtr, InetAddr); // 注InetAddr 为类该对象中包含目标端的IP地址、端口号class Tcp_Server { private:SockSPtr _listen_sockfd; // 监听套接字使用listen函数设置为监听态负责监听来自客户端的连接请求bool _is_running;uint16_t _port;Tcp_Server_FuncType _tcp_service; // 服务端需要执行的任务对象 public:// 构造函数提供端口号Tcp_Server(Tcp_Server_FuncType tcp_service, uint16_t port gport): _port(port), _listen_sockfd(std::make_sharedTcp_Socket()), _is_running(false), _tcp_service(tcp_service){}void InitServer(){// 1、 创建监听套接字// 2、绑定本地ip地址和port端口号// 3、将套接字设置为【监听状态】 以监听来自客户端的连接请求_listen_sockfd-BuildListenSocket(_port);}// 运行服务端void Loop(){// 多线程版本_is_running true;while(_is_running){// 1、获取来自客户端的连接请求并获得I/O专用套接字InetAddr from_client;SockSPtr _io_sockfd _listen_sockfd-Accepter(from_client);pthread_t tid 0;ThreadData * thread_data new ThreadData(_io_sockfd, this, from_client);// 线程需要执行类中的Service函数同时主线程不能对该线程进行等待回收所以需要该线程进行线程分离让线程退出后自动由系统回收if(pthread_create(tid, nullptr, ThreadRoute, thread_data) 0){LOG(FATAL, Thread Create False!);exit(-1);}}}// 为什么要单独设置一个线程数据类呢// 如果在Tcp_Server类中设置一个静态方法该方法无法访问类中的非静态成员。当然将Tcp_Server类对象本身的指针作为线程函数的参数传递给线程执行函数也是可以的// 但是服务器类对象中包含的成员变量和方法或许会非常多而线程执行函数仅需执行IO工作和对信息的处理工作并不需要这些数据。所以我们单独设计一个内部类// 在该类中添加所需的成员变量即可class ThreadData{public:SockSPtr _io_sockfd; // 进行io通信的套接字描述符Tcp_Server* _self; // Tcp_Server类指针用于调取该类中的函数方法InetAddr _net_addr; // ip portpublic:ThreadData(SockSPtr io_sockfd, Tcp_Server* self, InetAddr net_addr): _io_sockfd(io_sockfd), _self(self), _net_addr(net_addr){}};// static void* ThreadRoute(void* thread_data){// 1、将该线程设置为分离态该线程运行结束后系统自动回收资源pthread_detach(pthread_self());// 2、运行任务函数ThreadData* thread_self_data static_castThreadData*(thread_data);thread_self_data-_self-_tcp_service(thread_self_data-_io_sockfd, thread_self_data-_net_addr);close(thread_self_data-_io_sockfd-Sockfd());delete thread_self_data;return nullptr;} }; TCP_Server_main.cc服务端运行逻辑  #include Tcp_Server_New.hpp #include Service.hpp #include NetCol.hpp //在命令行需自主输入绑定的端口号 int main(int argc, char* argv[]) {if(argc 2){std::cout 未输入端口号... std::endl;exit(-1);}uint16_t port std::stoi(argv[1]);NetCal net_calculator;// 为服务类绑定 请求-》应答 方法IO_Service service(std::bind(NetCal::Calculator, net_calculator, std::placeholders::_1));// 绑定命令类中的命令处理方法作为服务端的执行函数构造服务端Tcp_Server server(std::bind(IO_Service::IOExecute, service, std::placeholders::_1, std::placeholders::_2), port);server.InitServer(); // 初始化服务端server.Loop(); // 启动服务端return 0; } TCP_Client.hpp客户端类 #pragma once #include sys/types.h #include sys/socket.h #include unistd.h #include string #include iostream #include arpa/inet.h #include cstring #include signal.h #include sys/wait.h #include Log.hpp #include Socket.hpp #include Protocol.hppstatic const int BUFFER_SIZE 256; const std::string opers -*/%^!; class Tcp_Client { private:SockSPtr _sockfd;std::string _to_server_ip;uint16_t _to_server_port;bool _is_running;public:Tcp_Client(const std::string ip, const uint16_t port): _to_server_ip(ip), _to_server_port(port), _sockfd(std::make_sharedTcp_Socket()){}~Tcp_Client(){_sockfd-Close();}void InitClient(){// 客户端无需手动绑定bind在使用connect函数连接时自动绑定IP地址和端口号// 1、创建套接字,连接服务端if (!_sockfd-BuildClientSocket(_to_server_ip, _to_server_port)){LOG(FATAL, BuildClientSocket fail!!!);}}// 启动客户端void Start(){_is_running true;while (_is_running){// // 1、输入需要计算的数字和操作符// int x, y;// char oper;// std::cout Please Enter X # ;// std::cin x;// std::cout Please Enter Operator # ;// std::cin oper;// std::cout Please Enter Y # ;// std::cin y;// 构建数据int x rand() % 10;usleep(x * 1000);int y rand() % 10;usleep(x * y * 100);char oper opers[y % opers.size()];// 2、根据输入信息创建请求std::shared_ptrRequest resquest std::make_sharedRequest(x, y, oper);// 3、将请求序列化获得序列化后的json串std::string json_str;if (!resquest-Serialize(json_str)){LOG(FATAL, request-DeSerialize fail!);}std::cout std::endl json_str;// 4、为序列化后的json串加码生成报文json_str AddCode(json_str);// 5、将报文发送给服务端if (_sockfd-Send(json_str) 0){LOG(FATAL, Client Write To Server False!\n);exit(-1);}LOG(INFO, Client Write To Server Success!\n);// 保证读取至少一条完整的报文while (true){// 6、接受来自服务端的应答std::string from_client_message;if (_sockfd-Recv(from_client_message) 0){LOG(FATAL, Client Write To Server False!\n);break;}// 7、对报文解码获取json串std::string from_client_json_str RemoveCode(from_client_message);if (from_client_json_str.empty()){continue;}// 8、根据json串构建应答std::shared_ptrResponse response std::make_sharedResponse();response-DeSerialize(from_client_json_str);// 9、打印应答结果response-PrintResult();break;}sleep(1);}_is_running false;} }; TCP_Client_main.cc客户端运行逻辑  #include Tcp_Client.hpp//在命令行需自主输入目标客户端的IP地址和需要绑定的端口号 int main(int argc, char* argv[]) {if(argc 3){std::cout 命令行参数过少... std::endl;exit(-1);}// 构造服务端Tcp_Client client(argv[1], std::stoi(argv[2]));client.InitClient(); // 构造客户端client.Start(); // 启动客户端return 0; } 通过上述代码我们可以理解协议实际上就是通信双方必须遵守提前约定好通信格式、信息的处理方式、错误检测与纠正机制、数据传输的顺序等方面的细节。 例如在HTTP协议中客户端和服务器之间的通信就是通过提前约定好的格式进行的。客户端发送一个HTTP请求服务器根据请求的内容返回相应的HTTP响应。HTTP协议规定了请求和响应的格式、状态码的含义、头部的字段等等这就是一种协议。 通过协议通信双方可以在不明确各自内部实现细节的情况下依然能够有效地进行数据交换和信息处理确保通信的准确性和可靠性。
http://www.w-s-a.com/news/430599/

相关文章:

  • 网站推广方式校园网站怎么建
  • 长沙seo网站排名怎么在百度发帖
  • 织梦贷款网站模板做印章网站
  • 彭州做网站上海百度网络推广
  • 广州网站搭建快速提升网站排名荧光字网站
  • 15年做那些网站能致富做seo是什么意思
  • 各电商网站的特点网站制作2007
  • 用html做一号店网站怎么做公众号注册平台官网
  • 做盈利网站怎么备案vs做网站如何调试
  • 嘉兴做营销型网站廊坊做网站外包
  • 双语网站模板常州做网站的公司
  • 广州市车管所网站建设全国做网站公司前十名
  • 太原手手工网站建设公司视频直播服务
  • 雷达图 做图网站wordpress首页怎么美化
  • 四川做网站设计公司价格vip解析网站怎么做的
  • 网站建设流程域名申请做化工的 有那些网站
  • 软件开发设计流程图seo搜索引擎官网
  • 外国小孩和大人做网站东富龙科技股份有限公司
  • 上线倒计时单页网站模板做网站的资金来源
  • 泸州市建设厅网站中小企业网络需求分析
  • asp网站版权做网页价格
  • 长春网站建设路关键词优化公司哪家好
  • 河南省建设银行网站年报天津设计师网站
  • 沙洋网站定制如果自己建立网站
  • 凡科网站怎么做建站关键字搜索网站怎么做
  • 小说网站建站程序企业邮箱地址
  • 福州市住房和城乡建设网站网站开发方案论文
  • 在线教育网站开发网站推广常用方法包括
  • 东莞高端品牌网站建设软件开发模型及特点
  • 个人网站的设计与实现的主要内容网站开发公司架构