男生做男生网站在那看,wordpress自动添加关键词和描述,诚客网站建设,网站商城微信支付宝支付宝支付接口1. 再谈 协议
协议是一种 约定#xff0c;在读写数据时, 都是按 字符串 的方式来发送接收的.
但是这里我们会遇到一些问题#xff1a;
如何确保从网上读取的数据是否是完整的#xff0c;区分缓冲区中的由不同客户端发来的数据 2. 网…
1. 再谈 协议
协议是一种 约定在读写数据时, 都是按 字符串 的方式来发送接收的.
但是这里我们会遇到一些问题
如何确保从网上读取的数据是否是完整的区分缓冲区中的由不同客户端发来的数据 2. 网络版计算器
举例我们需要实现一个服务器版的加法器. 我们需要客户端把要计算的两个加数发过去, 然后由服务器进行计算, 最后再把结果返回给客户端
约定方案一:
客户端发送一个形如11的字符串;
这个字符串中有两个操作数, 都是整形;
两个数字之间会有一个字符是运算符, 运算符只能是 ;
数字和运算符之间没有空格;
结果不可取,无法判断从网上读取的数据是否是完整的 约定方案二:
定义结构体来表示我们需要交互的信息;
发送数据时将这个结构体按照一个规则转换成字符串这个过程叫做 序列化, 接收到数据的时候再按照相同的规则把字符串转化回结构体;这个过程叫做“反序列化” 自定义序列化反序列化 #includeiostream
#includesys/socket.h
#includesys/types.h
#includenetinet/in.h
#includearpa/inet.h
#includestring
#includememory
#includeunistd.h
using namespace std; #includehead.hpp
class sock
{
public:sock(uint16_t port 8080):_port(port){}void Init(){fd socket(AF_INET,SOCK_STREAM,0);if(fd 0){cout socket fail endl;exit(1);}}void Bind(){sockaddr_in addr;addr.sin_family AF_INET;addr.sin_port htons(_port);addr.sin_addr.s_addr inet_addr(0.0.0.0);socklen_t len sizeof(addr);int n bind(fd,(struct sockaddr*)addr,len);if(n 0){cout bind fail endl;exit(2);}}void Listen(){int n listen(fd,0);if(n 0){cout listen fail endl;exit(3);}}void Accept(int client_fd){sockaddr_in addr;socklen_t len sizeof(addr);client_fd accept(fd,(struct sockaddr*)addr,len);if(client_fd 0){cout accept fail endl;}else{cout get a new link ... endl;}}int Connect(const uint16_t port,const string s){sockaddr_in addr;addr.sin_family AF_INET;addr.sin_port htons(port);addr.sin_addr.s_addr inet_addr(s.c_str());socklen_t len sizeof(addr);int n connect(fd,(struct sockaddr*)addr,len);if(n 0){cout connect fail endl;exit(4);}return fd;}
private:int fd;uint16_t _port;
}; #includestring
string package(const string content)
{//len\ncontent\nint n content.size();string s to_string(n);s \n;s content;s \n;return s;
}
string prase(string package)
{//len \n content \nsize_t pos package.find(\n);if(pos string :: npos){return nullptr;}int len_package package.size();string l package.substr(0,pos);int len stoi(package.substr(0,pos));if(l.size() 2 len len_package){return nullptr;}string s;s package.substr(pos 1,len);package.erase(0,l.size() 2 len);return s;}
struct protocol_client
{protocol_client(int x 0,int y 0,char op ):_x(x),_y(y),_op(op){}string serialize(){// _x _op _ystring s;s to_string(_x);s ;s _op;s ;s to_string(_y);return s;}void deserialize(const string s){int left s.find( );if(left string :: npos){cout protocol_client : find fail endl;}int right s.rfind( );if(right string :: npos){cout protocol_client : find fail endl;}if(left 2 ! right){cout protocol_client : deserialize fail endl;return ;}_x stoi(s.substr(0,left));_y stoi(s.substr(right 1));_op s[left 1];}int _x;int _y;char _op;
};
struct protocol_server
{protocol_server(int result 0,int code 0):_code(code), _result(result){}string serialize(){//_result _codestring s;s to_string(_result);s ;s to_string(_code);return s;}void deserialize(const string s){size_t pos s.find( );if(pos string :: npos){cout protocol_client : find fail endl;}_result stoi(s.substr(0,pos));_code stoi(s.substr(pos 1));}int _code;
int _result;
}; #includeserver.hpp
int main()
{unique_ptrserver sv(new server());sv-start();sv-run();return 0;
} #include sock.hpp
#includeprotocol.hpp
class server
{
public:server(){}void start(){svr.Init();svr.Bind();svr.Listen();}void run(){int client_fd;svr.Accept(client_fd);string e;while(true){//读端char buff[1024];ssize_t n read(client_fd, buff, sizeof(buff));if (n 0){cout server : read fail endl;}buff[n] 0;e buff;string s prase(e);protocol_client sv;sv.deserialize(s);//计算int result,code 0;switch(sv._op){case :result sv._x sv._y;break;case -:result sv._x - sv._y;break;case *:result sv._x * sv._y;break;case /:if(sv._y 0){code 1;}else{result sv._x / sv._y;}break;default:code 2;}protocol_server ss(result,code);s ss.serialize();s package(s);//写端n write(client_fd,s.c_str(),s.size());if(n 0){cout server : write fail endl;}}}
private: sock svr;
}; #includesock.hpp
#includeprotocol.hpp
void usage()
{cout x y ? endl;
}int main()
{uint16_t port 8080;sock client;client.Init();int fd client.Connect(port,1.94.49.66);string e;while(true){usage();int x,y;char op;//写端cout please enter: x ;cin x;cout please enter: op ;cin op;cout please enter: y ;cin y;protocol_client sv(x,y,op);string s sv.serialize();s package(s);ssize_t n write(fd,s.c_str(),s.size());if(n 0){cout client : write fail endl;}//读端char buff[1024];n read(fd,buff,sizeof(buff));if(n 0){cout client : read fail endl;}buff[n] 0;e buff;s prase(e); protocol_server ss;ss.deserialize(s);cout result : ss._result code : ss._code endl;cout ------------------------------------------------------------- endl endl;}return 0;
} json类 #includejsoncpp/json/json.h
int main()
{Json::Value root;root[x] 100;root[y] 200;root[op] ;root[dect] this is a oper;Json::FastWriter w;string res w.write(root);cout res endl;return 0;
} Json::Value v;
Json::Reader r;
r.parse(res,v);
int x v[x].asInt();
int y v[y].asInt();
char op v[op].asInt();
string dect v[dect].asString(); 3. HTTP协议
一认识 HTTP协议
应用层协议是我们程序员自己定的但实际上, 已经有一些现成的, 又非常好用的应用层协议, 供我们直接参考使用如 HTTP(超文本传输协议) 就是其中之一. 二认识URL
平时我们说 网址 就是URL 注意
像网站这种一般默认会添加协议方案名且协议方案名对应唯一一个端口号所以即使不写端口号也没关系如http 对应端口号 80https 对应端口号 443)web根目录不一定是linux系统下的根目录具体指什么完全由服务器那边解释 三urlencode编码 和 urldecode解码
像 / ? : 等这样的字符, 已经被url当做特殊意义理解了. 因此这些字符不能随意出现
所以如果某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义. 转义的规则如下这个过程叫编码:
将需要转码的字符转为16进制然后从右到左取4位(不足4位直接处理)每2位做一位前面加上%编码成%XY格式 编码解码工具
URL 编码解码 - Codeeeee 在线小工具 4. HTTP协议格式 注意
上图对应格式是打印出来的格式实际上发送到网络上的是整个字符串是连在一起的http也是一种协议它也需要将数据序列化反序列化 代码 5. HTTP的方法 其中最常用的就是 GET方法 和 POST方法
注意
GET 方法 和 POST 方法都可以传参GET 方法的参数是在 url 内的,通过 url 提交的POST 方法的参数是在正文内POST 方法 比 GET 方法更加私密 GET 方法 POST 方法 6. HTTP的状态码 最常见的状态码, 比如 200(OK), 404(Not Found一般是客户端要访问的文件不存在), 403(Forbidden), 302(Redirect, 重定向), 504(Bad Gateway)
注意
3XX代表的重定向有两种一种是临时移动另一种是长期移动长期移动一旦设置了永久重定向所有后续对原始URL的请求都应该被自动转发到新的URL而且这个重定向是长期有效的临时移动表明资源的移动是暂时的。 客户端在接收到临时重定向响应后会临时使用新的URL但在将来的某个时间点对原始URL的请求可能会恢复为直接访问原始资源而不是被重定向 HTTP常见Header
Content-Type: 数据类型(text/html等)
Content-Length: Body的长度
Host: 客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上;
User-Agent: 声明用户的操作系统和浏览器版本信息;
referer: 当前页面是从哪个页面跳转过来的;
location: 搭配3xx状态码使用, 告诉客户端接下来要去哪里访问;
Cookie: 用于在客户端存储少量信息. 通常用于实现会话(session)的功能 注意
Content-Type 指明访问的路径是什么类型如.html : 网页 .jpg jpg格式的图片 .png png格式的图片 ...... )Cookie Cookie文件可能是内存级的储存在内存里也可能是文件级的储存在磁盘里 cookie文件的内容保存多久一般是由浏览器决定的如果内容没有了则下一次访问对应服务器仍要进行验证http协议默认是无状态的http对登入用户的会话保持功能 7. 长连接和短连接
即使是一个网页也可能包含很多元素每一个元素都要进行一次http请求,即建立一个tcp连接就会发生多个请求和响应这就是长连接只有一次请求和响应连接就断开的就是短连接