前言
已经开始工作了,以后的技术路线是这样的
linux(使用)
-> 网络(硬件)
-> 运维(docker)
-> 网络安全
兜兜转转发现自己做了不少和网络相关的项目/经历, 有感而发, 因此写一写, 就以时间为顺序吧
202308 muduo库 - C++
- 其实就是使用
socket
编程, 当接受到字节流信息的时候, 如何进行操作
- 实现了
http
协议
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
POST /index.html HTTP/1.1 #(回车换行)
Who: Alex #(回车换行)
Content-Type: text/plain
Host: 127.0.0.1:8888
Content-Length: 28
Cookie: JSESSIONID=24DF2688E37EE4F66D9669D2542AC17B #(回车换行)
#(回车换行)
Let's watch a movie together
# 响应报文
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: application/json
Transfer-Encoding: chunked
Date: Mon, 12 Sep 2011 12: 41: 24 GMT
6f
{"password":"1234","userName":"tom","birthday":null,"salary":0,
"realName": "tomson","userId": "1000","dept":null}
0
|
HttpContext主要的功能:
- 处理
http
报文, 将报文解析出来, 传入成员HttpRequest
中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class HttpContext{
public:
enum HttpRequestParseState{
kExpectRequestLine, // 期望解析请求行
kExpectHeaders, // 期望解析请求头部
kExpectBody, // 期望解析请求体
kGotAll, // 已经解析完整请求
};
bool parseRequCest(Buffer* buf, Timestamp receivetime);
private:
HttpRequestParseState state_;
HttpRequest request_;
};
|
将连接设计为一个类
存储了连接的状态, URL
以及 headers
类的对象有
- 1 方法, 具体用的什么
子协议
, 是post
还是get
这关系到以后怎么解析报文
- 2 版本, 这也关系到如何解析报文
- 3 头部, 鉴权信息等
https://www.example.com/product/123?category=electronics&sort=price_asc,
- path_的值为/product/123
- query_的值为category=electronics&sort=price_asc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
class HttpRequest{
public:
using HttpMap= map<string, string> ;
enum Method{
kInvalid, kGet, kPost, kHead, kPut, kDelete
};
enum Version{
kUnkown, kHttp10 , kHttp11
};
private:
Method method_;
Version version_;
std::string path_;
std::string query_;
Timestamp receiveTime_;
std::map<string, string> headers_;
};
|
202310 为 天若 OCR 添加 latex api - C#
本段代码逻辑
结构
- 通过
http
来获取服务
- 对结果进行解析
- 返回
json
字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public static string OCR_Custom(Image image)
{
//string url = "";
//string poststr ="";
//string result =CustomHelp.HttpPost(url,poststr);
//获取请求获取解析结果后按照下面格式进行解析
TxtFormat.Root jsonRoot=new TxtFormat.Root();
jsonRoot.result=new List<TxtFormat.TextBlock>();
jsonRoot.isHasLocation=true;//判断是否含有坐标返回
for(int i=0; i<5; i++)//遍历返回的json字符串
{
TxtFormat.TextBlock textBlock = new TxtFormat.TextBlock();
textBlock.Text = "公式测试文本"+i.ToString();//json内的文本
textBlock.TopLeft = new Point(0,0);//左上角坐标
textBlock.TopRight = new Point(0,0);//右上角坐标
textBlock.BottomRight =new Point(0,0);//右下角坐标
textBlock.BottomLeft =new Point(0,0);//左下角坐标
jsonRoot.result.Add(textBlock);
}
string json = JsonConvert.SerializeObject(jsonRoot);
return json;
}
|
我的错误
- 一开始认为
CustomHelp.HttpPost()
是一个具体的类, 但是也没有一个demo来说明各个参数的意义, 因此认为是伪码, 所以认为下面的也全是伪代码, 让我付出了惨重的代价
- 实际上就应该是一个具体的类, 因为后文的TxtFormat等也是具体的类, 但是没有使用说明, 就只能使用 HttpWebResponse库交换 http报文
天若开源版本的代码
- 猜测typeset_txt 就是显示的内容, 也是 接口中返回的原始字符串对应起来
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
var img = image_screen;
var inArray = OcrHelper.ImgToBytes(img);
var s = "{\t\"formats\": [\"latex_styled\", \"text\"],\t\"metadata\": {\t\t\"count\": 0,\t\t\"platform\": \"windows 10\",\t\t\"skip_recrop\": true,\t\t\"user_id\": \"\",\t\t\"version\": \"snip.windows@01.02.0027\"\t},\t\"ocr\": [\"text\", \"math\"],\t\"src\": \"data:image/jpeg;base64," + Convert.ToBase64String(inArray) + "\"}";
var bytes = Encoding.UTF8.GetBytes(s);
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://api.mathpix.com/v3/latex");
httpWebRequest.Method = "POST";
httpWebRequest.ContentType = "application/json";
httpWebRequest.Timeout = 8000;
httpWebRequest.ReadWriteTimeout = 5000;
httpWebRequest.Headers.Add("app_id: mathpix_chrome");
httpWebRequest.Headers.Add("app_key: 85948264c5d443573286752fbe8df361");
using (var requestStream = httpWebRequest.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
}
var responseStream = ((HttpWebResponse)httpWebRequest.GetResponse()).GetResponseStream();
var value = new StreamReader(responseStream, Encoding.GetEncoding("utf-8")).ReadToEnd();
responseStream.Close();
var text = "$" + ((JObject)JsonConvert.DeserializeObject(value))["latex_styled"] + "$";
split_txt = text;
typeset_txt = text;
|
simpletex API 的python调用
1
2
3
4
5
6
7
8
|
import requests
api_url="https://server.simpletex.cn/api/latex_ocr/v2" # 接口地址
data = { } # 请求数据
header={ "token": "" } # 鉴权信息,此处使用UAT方式
file=[("file",("test.png",open("test.png", 'rb')))] # 请求文件,字段名一般为file
res = requests.post(api_url, files=file, data=data, headers=header) # 使用requests库上传文件
print(res.status_code)
print(res.text)
|
1
2
3
4
5
6
7
|
{
"status": true/false, // 是否成功调用接口
"res": { // 调用结果
...
},
"request_id": "tr_xxxxxxxxxx" // 请求ID
}
|
如何输出错误
- 发现 MessageBox.Show()能输出信息, 就用它来调试
1
|
MessageBox.Show(responseContent.ToString() );
|
协议 post 的数据格式
- 边界符:
boundary=AaB03x
- Post 中定义的换行符是 \r\n, 每一个边界符前面都需要加 2 个连字符 “–”,然后跟上换行符。
- 使用Content-Type 指定发送或接收实体正文的媒体类型
Content-Type
由两部分组成,用斜杠分隔:媒体类型(media type)和子类型(subtype)。常见的媒体类型包括:
text/plain
:纯文本类型。
text/html
:HTML 文档类型。
application/json
:JSON 数据类型。
application/xml
:XML 数据类型。
- application/octet-stream : 二进制数据.
image/jpeg
:JPEG 图片类型。
audio/mpeg
:MPEG 音频类型。
video/mp4
:MP4 视频类型。
Content-Disposition
:该头部字段用于指示如何处理包含在消息体中的数据。它可以指定将数据显示在浏览器窗口中、作为附件下载、保存到磁盘等行为。常见的值包括:
inline
:默认值,将数据在浏览器中显示。
attachment
:将数据作为附件下载。
filename=<文件名>
:指定下载时的文件名。
- Content-Disposition: form-data; name=“file”; filename=“file1.dat”, 通常是用在客户端向服务端传送大文件数据,如:图片或者文件
- 使用
boundary
来分隔文件
- 数据结束后的分界符,注意因为这个后面没有数据了所以需要在后面追加一个 “–” 表示结束。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// 来自 https://blog.csdn.net/flymorn/article/details/6769722
Content-Type: multipart/form-data; boundary=AaB03x
--AaB03x
Content-Disposition: form-data; name="submit-name"
Larry
--AaB03x
Content-Disposition: form-data; name="file"; filename="file1.dat"
Content-Type: application/octet-stream
... contents of file1.dat ...
--AaB03x--
|
完整代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
public static string OCR_Custom(Image image)
{// Image 是一个类,它是用于处理图像和图形的基本类之一。
byte[] result;
using (var memoryStream = new MemoryStream())
{
image.Save(memoryStream, ImageFormat.Png);
result = memoryStream.ToArray();
}
// request
string url = "https://server.simpletex.cn/api/latex_ocr/v2";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = "multipart/form-data;boundary=---------------------------boundary";
request.Method = "POST";
request.Headers["token"] = "";
string boundary = "---------------------------boundary";
byte[] boundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n");
string formDataTemplate = "--{0}\r\nContent-Type:application/octet-stream\r\nContent-Disposition: form-data; name=\"file\"; filename=\"image.png\"\r\nContent-Type: image/png\r\n\r\n";
string formData = string.Format(formDataTemplate, boundary);
byte[] formDataBytes = Encoding.UTF8.GetBytes(formData);
// 设置请求体长度
request.ContentLength = formDataBytes.Length + result.Length + boundaryBytes.Length;
// 将请求体数据写入请求流中
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(formDataBytes, 0, formDataBytes.Length);
requestStream.Write(result, 0, result.Length);
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
}
// 发送请求并获取响应
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
// 处理响应
string responseContent;
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
responseContent = reader.ReadToEnd();
// Console.WriteLine(responseContent);
}
response.Close();
var resultData = ((JObject)JsonConvert.DeserializeObject(responseContent));
var data = resultData["res"];
var region = data["latex"];
var text = "$" +region.ToString() + "$";
TxtFormat.Root jsonRoot=new TxtFormat.Root ();
jsonRoot.result=new List<TxtFormat.TextBlock>();
jsonRoot.isHasLocation=true;// 判断是否含有坐标返回
TxtFormat.TextBlock textBlock = new TxtFormat.TextBlock ();
textBlock.Text = text;//json 内的文本
textBlock.TopLeft = new Point (0,0);// 左上角坐标
textBlock.TopRight = new Point (0,0);// 右上角坐标
textBlock.BottomRight =new Point (0,0);// 右下角坐标
textBlock.BottomLeft =new Point (0,0);// 左下角坐标
jsonRoot.result.Add (textBlock);
// `SerializeObject(object value)`:将对象序列化为 **JSON 字符串**。
return JsonConvert.SerializeObject (jsonRoot);
}
|