五、市面上常用序列化和反序列化工具
常用的有:json、protobuf、xml三种方案;
5.1json的使用
1.安装jsoncpp库,是一个第三方的开发库文件;
sudo yum install -y jsoncpp-devel
2.使用json
经常使用的头文件是json.h,
使用的动态库文件;
3.json语法
#include <jsoncpp/json/json.h>
//序列化
//1.创建Value对象
Json::Value root;
//Value是万能类,重载了[],返回值是Value对象引用,它的内部是一堆kv的形式;甚至可以放Value;
//root.size()是根据k来划分的;
//2.设置Value
root["x"] = 100;
root["y"] = 200;
root["op"] = '+';
root["desc"] = "this is a add algorithm";
//3.序列化Value
//有两种方式
//3.1对象实例化
Json::FastWriter w;
Json::StyledWriter w;//好处是可读性更好一些
//3.2进行序列化
w.write(root);
//一个参数为Value对象;
std::cout << root << std::endl;
std::cout << w.write(root) << std::endl;
//4.反序列化Value
//4.1创建Value缓冲区和reader对象
Json::Value v;
Json::Reader r;
//4.2进行反序列化
r.parse(str,v);
//第一个参数是要进行反序列化的字符串;
//第二个参数是缓冲区;
//第三个参数表示是否有效,默认使用缺省参数;
//5.将Value对象解析成有效对象,使用as系列转换成有效的数据
int x = v["x"].asInt();
int y = v["y"].asInt();
char op = v["op"].asInt();
std::string desc = v["desc"].asCString();
std::cout << desc << " " << x << " " << op << " " << y << std::endl;
六、重谈ISO7层模型
6.1会话层
实际上在代码当中体现为tcp服务端和客户端获取连接和发起连接,负责管理好连接;
6.2表示层
其实就是指定制协议与序列化和反序列化,数据在网络中的转化;
6.3应用层
针对特定应用的协议;
七、http协议
7.1统一资源定位符
在平常的生活中,访问服务器其实使用的不是IP地址,而是域名这样的东西;域名的作用就是提高用户的体验,直接使用IP地址可读性较差,使用域名间接转换为IP地址这种方式可读性更好,更容易让人们接受这种使用方式;
在浏览器中网址位置输入IP地址,会自动将39.156.66.14IP地址添加一些字段变为"http 😕/39.156.66.14/",浏览器中默认使用的协议一般是http或者https,会默认进行拼接的;这些协议服务的端口号一般是得固定下来,如:http是80,https是443,所以在拼接协议字段的时候是默认增加了端口号的;
url叫做统一资源定位符;由协议(服务的端口号)+域名(远端主机的IP地址)+资源路径,使用统一资源定位符,通过唯一路径定位,就可以在网上找到资源;其实就是在远端的主机上,使用服务进程并通过资源路径来查找主机内的资源;
网络行为一般有两种:1.下载;2.上传;
使用?k=v这种形式,来提交参数,多个参数可以使用&来进行划分支持多参数提交;
7.2urlencode和urldecode
在使用url的时候,少量的情况会将提交或者获取的数据(可能包含和url中特殊字符冲突的字符),要求浏览器和服务器双方之间要进行编码(encode)和解码(decode);
编码和解码防止和数据和url本身冲突;
编码的规则是将需要转码的字符(在ASCII码中对应一个数,一个字节大小)转换为16进制,然后从右向左取4位,不足4位的每两位为1位,在前面加上%,编码成%xy的形式;
网上也有在线进行编码和解码的工具;
7.3http请求和响应
无论是请求还是响应都是以行的形式来陈列请求和响应;
7.3.1http请求格式
由请求行、请求报文、空行、请求正文构成;
请求行
1.请求行之中除了结尾是不可以再出现回车换行符的;2.请求行的报头字段共有三部分,第一部分是请求方法,一般使用两种,一种叫做get方法,一种叫做post方法;第二部分以空格作为分隔符和第一部分区分,具体内容是URL,表示当前当前要请求的资源是谁;第三部分和第二部分也是使用空格作为分隔符,叫做请求的协议版本,即http版本,包括1.0 1.1 2.0,格式为http/1.1;注意需要是大写的;
请求报文
由多行构成,每一行都叫做http的请求属性;这些属性大部分是键值对的形式;
空行
\r\n在行的最开始位置,通过行读取的方式,将报头和有效载荷分离;
请求正文
要上传的内容;
无法保证读到完整的正文,但是可以保证读到完整的请求报头;而报头的属性有 表示正文长度的字段,然后根据此属性读到一个完整的报文;
7.3.1http响应格式
与请求类似;
状态行
包括三部分,第一部分http版本(便于进行划分功能),第二部分状态码,第三部分为状态码描述;如:404 Not Found;对于请求必须有响应;
7.4使用工具进行http响应的抓取
1.telnet
telnet www.baidu.com 80
最简单的请求报头和报文是可以没有的,但是请求行和空行必须有;所以如下操作之后即可获得一个响应;
GET / HTTP/1.1
如下就是一个响应报文;
2.fiddler
基于http进行抓包;fiddler工具就是一种代理,本来是浏览器访问服务器,变成了fiddler工具代理,进行请求包装和获取响应,然后再返回给浏览器;
3.postman
当成浏览器使用;
7.5实现一个简单的http服务
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
//也可以用来进行tcp读取
//与read类似,多了第四个参数可以设置读取的方式
//0表示阻塞的方式
#pragma once
#include <iostream>
#include <string>
#include <pthread.h>
#include <unistd.h>
#include "Socket.hpp"
#include "Log.hpp"
const uint16_t defaultport = 8888;
class threadinfo
{
public:
threadinfo(int sockfd) : sockfd_(sockfd) {}
public:
int sockfd_;
};
class httpserver
{
public:
httpserver(uint16_t port = defaultport) : port_(port) {}
~httpserver() {}
public:
static void httphandler(int sockfd)
{
char buff[10240];
ssize_t n = recv(sockfd, buff, sizeof(buff) - 1, 0);
if (n > 0)
{
buff[n] = 0;
std::cout << buff;
// 返回一个响应
std::string text = "<html><body><h3>hello world</h3></body></html>";
std::string response_line = "HTTP/1.0 200 OK\r\n";
std::string response_header = "Content-Length: ";
response_header += std::to_string(text.size());
response_header += "\r\n\r\n";
std::string response;
response += response_line;
response += response_header;
response += text;
send(sockfd, response.c_str(), response.size(), 0);
}
close(sockfd);
}
static void *routine(void *args)
{
pthread_detach(pthread_self());
threadinfo *hs = static_cast<threadinfo *>(args);
httphandler(hs->sockfd_);
delete hs;
return nullptr;
}
bool start()
{
listensockfd_.Socket();
listensockfd_.Bind(port_);
listensockfd_.Listen();
// lg(Info, "init done...");
while (true)
{
std::string clientip;
uint16_t clientport;
int sockfd = listensockfd_.Accept(&clientip, &clientport);
if (sockfd < 0)
continue;
pthread_t tid;
threadinfo *td = new threadinfo(sockfd);
pthread_create(&tid, nullptr, routine, (void *)td);
}
}
private:
uint16_t port_;
Sock listensockfd_;
};
1.可以通过User-Agent来设计反爬策略;2.浏览器下载app,通过User-Agent的属性,来推送相关系统的软件;
http对于请求会创建一个响应,添加报头、空行和正文,包括将网页拼接到正文部分;发送过来的请求可能会包含请求什么网页,什么资源,通过url呈现出来;
7.6web根目录
wwwroot是web根目录,存放了允许别人访问的所有资源;
可以直接在本地修改文件,通过浏览器直接访问到修改后的结果;