我的网络编程回顾-20241018

前言

已经开始工作了,以后的技术路线是这样的

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调用

  • 使用 post 方法
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);
	}
	
Licensed under CC BY-NC-SA 4.0
最后更新于 Oct 22, 2024 20:36 +0800
使用 Hugo 构建
主题 StackJimmy 设计