HTTP(网络)

devtools/2024/11/30 8:30:27/

目录

1.Http的基本代码

1.1 HttpServer.hpp

1.2 简单测试一下

 1.3 用telnet测试一下

1.4 用浏览器访问

1.5 返回相应的过程(网页版本)​编辑

1.5.1 再次用浏览器访问

1.6 返回相应的过程(文件版本)

 1.6.1网页

 1.6.2 测试

1.7 反序列化截取

1.7.1 解析第一行 vector 0号下标里的字符串

1.7.1.1 stringstream分割符号

1.7.1.2 首页的设置 

1.7.2 访问别的网页(这里有3张网页 )

1.8 跳转网络链接​编辑

1.8.1 跳转到自己创建的网页

2.Http的细节字段

3.HTML 表单,输入账号和密码

3.1 get方法(不私密)

3.2 post方法

4. HTTP常见的Header​编辑

5.长短链接

http-10)-toc" style="margin-left:40px;">5.1 短连接(HTTP 1.0)

C/C++ 中的短连接示例:

http-11)-toc" style="margin-left:40px;">5.2 长连接(HTTP 1.1)

C/C++ 中的长连接示例:

5.3 关键区别总结

5.4 长短连接的选择

6.图片

​编辑

7.cookie文件(记住密码)

8.HTTP协议

8.1 认识URL(网址)

8.2 urlencode和urldecode

9.HTTP协议格式

10.HTTP的方法

11.HTTP的状态码

12.HTTP常见Header

13.最简单的HTTP服务器

抓包工具 

https://i-blog.csdnimg.cn/direct/b167d19fc22046cd84ffcb8deb708993.png" width="195" />

https://i-blog.csdnimg.cn/direct/94c9493a47f44f07adc29a483ba71329.png" width="118" />

1.Http的基本代码

https://i-blog.csdnimg.cn/direct/fd950bb6f9514e178bdb7ca60a792dc2.png" width="249" />

1.1 HttpServer.hpp

#pragma once
#include <iostream>
#include <string>
#include <pthread.h>
#include "Socket.hpp"
#include "logs/ljwlog.h"using namespace std;
static const int dafaultport = 8080;struct ThreadData
{int sockfd;
};class HttpServer
{
public:HttpServer(uint16_t port = dafaultport):port_(port){}bool Start(){listensock_.Socket();listensock_.Bind(port_);listensock_.Listen();for(;;){string clientip;uint16_t clientport;int sockfd = listensock_.Accept(&clientip, &clientport);pthread_t tid;ThreadData *td = new ThreadData();td->sockfd = sockfd;pthread_create(&tid, nullptr, ThreadRun, td);}}//把收到的信息打印出来static void *ThreadRun(void *args){pthread_detach(pthread_self());ThreadData *td = static_cast<ThreadData*>(args);char buffer[10240];//跟read用法很像ssize_t n = recv(td->sockfd, buffer, sizeof(buffer), 0);if(n > 0){buffer[n] = 0;cout<< buffer;}close(td->sockfd);delete td;return nullptr;}~HttpServer(){}
private:uint16_t port_;Sock listensock_;
};

1.2 简单测试一下

https://i-blog.csdnimg.cn/direct/67b8d940a4bc42f285b78379e0deb4af.png" width="1200" />

https://i-blog.csdnimg.cn/direct/3440c93d7e2e4bbc8d6445394c6c1878.png" width="1200" />

 1.3 用telnet测试一下

https://i-blog.csdnimg.cn/direct/29d4190d36724fb799a3315f2a8205a9.png" width="1200" />

1.4 用浏览器访问

https://i-blog.csdnimg.cn/direct/f6fe6f42ef6c49fbadaed8c34faf5e75.png" width="661" />

1.5 返回相应的过程(网页版本)https://i-blog.csdnimg.cn/direct/087600e6117d42cb9e3f17b275e7fbbf.png" width="877" />

https://i-blog.csdnimg.cn/direct/a0497949eb744de7806861075c77535d.png" width="1200" />

1.5.1 再次用浏览器访问

https://i-blog.csdnimg.cn/direct/103c4a6deb4748a2a0d24692b3dbdef1.png" width="700" />

1.6 返回相应的过程(文件版本)

https://i-blog.csdnimg.cn/direct/5afbd5ea4a08403eb3c45f2a091aa23b.png" width="1155" />

 1.6.1网页

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" const="width=device-width,initial-scale=1.0"><title>Document</title>
</head>
<body><h1>hello world</h1>
</body>
</html>

https://i-blog.csdnimg.cn/direct/7afce46979094587b4dcdc3497217aec.png" width="1200" />

https://i-blog.csdnimg.cn/direct/6be896d3b1cd4194966859d22c9462c4.png" width="1200" />

 1.6.2 测试

https://i-blog.csdnimg.cn/direct/f24faafc054e40348ca2db293ffef5d0.png" width="928" />

更改一下写的网页,服务器不用关,浏览器刷新一下就可以

https://i-blog.csdnimg.cn/direct/cbd4285aed214ce8ba07abe7c4098dd5.png" width="1200" />

https://i-blog.csdnimg.cn/direct/6339d6d0704342a4a10231b08f14cb1c.png" width="858" />

https://i-blog.csdnimg.cn/direct/8626d1cde6604337aea5e124c9c3a4d0.png" width="621" />

1.7 反序列化截取

https://i-blog.csdnimg.cn/direct/ee607a17087844569e49a6426d185667.png" width="618" />

https://i-blog.csdnimg.cn/direct/2f8e2ce0865b4e1695bf1f90893c1d09.png" width="1200" />

https://i-blog.csdnimg.cn/direct/ca6f873602b246b381e3b3793a10ea1f.png" width="1177" />

1.7.1 解析第一行 vector 0号下标里的字符串

https://i-blog.csdnimg.cn/direct/3a49a5e4e5d84145b0b4bd81d9afd2f5.png" width="988" />

https://i-blog.csdnimg.cn/direct/64ecbf2e190d477f84c35653225030fc.png" width="972" /> https://i-blog.csdnimg.cn/direct/6647b8a67d634ee5bb6d4d6a165b706e.png" width="1030" />

https://i-blog.csdnimg.cn/direct/6095fcff78d347739d9cb3678bf5d247.png" width="1200" /> https://i-blog.csdnimg.cn/direct/abfada254327406293eed6690930aa79.png" width="990" />

1.7.1.1 stringstream分割符号

stringstream流式分隔符:stringstream - C++ Reference (cplusplus.com)

https://i-blog.csdnimg.cn/direct/78b5d28c09ab4841a81fe46230214594.png" width="972" />

1.7.1.2 首页的设置 

https://i-blog.csdnimg.cn/direct/2a0184f4b645471ca8692740a5b4013c.png" width="1200" />

https://i-blog.csdnimg.cn/direct/2279672bd6844dd7af39d54620a7a921.png" width="934" />

https://i-blog.csdnimg.cn/direct/c3f8deb8501d4649a336c4c0323eaa6d.png" width="1200" />https://i-blog.csdnimg.cn/direct/816656610be84561b45d6182dd419e3e.png" width="1200" />

1.7.2 访问别的网页(这里有3张网页 )

https://i-blog.csdnimg.cn/direct/ddae1295c676430d8bd22ff5df76432f.png" width="220" />

https://i-blog.csdnimg.cn/direct/962c033778364e9f885e5a9432f15b8b.png" width="709" />

先开启服务器

https://i-blog.csdnimg.cn/direct/34105ee1db1a468785e873912be495c1.png" width="633" />

https://i-blog.csdnimg.cn/direct/aba74cbc35554f9c90cfa93988da51a8.png" width="1200" />

1.8 跳转网络链接https://i-blog.csdnimg.cn/direct/6f4898e12c9d47b0a077ac77a162d95a.png" width="1200" />

https://i-blog.csdnimg.cn/direct/36a8c85277b149efb5a5bad4e91efb9a.png" width="685" />

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" const="width=device-width,initial-scale=1.0"><title>Document</title>
</head>
<body><h1>hello world</h1><h1>hello world</h1><h1>hello world</h1><h1>hello world</h1><h1>hello world</h1><h1>hello world</h1><a href="https://blog.csdn.net/2401_83427936?spm=1000.2115.3001.5343">Ljw的博客链接</a>
</body>
</html>

1.8.1 跳转到自己创建的网页

https://i-blog.csdnimg.cn/direct/b78e448b1a7745c38f7bb3f22a6a396c.png" width="1200" />

https://i-blog.csdnimg.cn/direct/4bee52f7131e4bcda214998770d4f875.png" width="853" />

2.Http的细节字段

3.HTML 表单,输入账号和密码

在这之间输入

https://i-blog.csdnimg.cn/direct/4e9dbd5e969542ac99748ffa9bb97abd.png" width="1200" />

HTML <form> 标签_w3cschoolhttps://i-blog.csdnimg.cn/direct/f1c185c123a744a6bd8c7a347db4e716.png" width="1002" />

3.1 get方法(不私密)

https://i-blog.csdnimg.cn/direct/6b85c3eacb0d4ce6a0b26ea20ab89771.png" width="1200" />

get后会把自己输入的账号密码放进链接后面了 

https://i-blog.csdnimg.cn/direct/af24caa20fed4ba4b92d839b8caefa04.png" width="1086" />

3.2 post方法

https://i-blog.csdnimg.cn/direct/9d62bddae17e49e7bb6a02b531865768.png" width="1200" />

https://i-blog.csdnimg.cn/direct/03b53bd6f57f45fd9284c2d10dec52af.png" width="553" />

4. HTTP常见的Headerhttps://i-blog.csdnimg.cn/direct/8347457a3f1e477dbb67542960933fb1.png" width="1200" />

https://i-blog.csdnimg.cn/direct/07326d529f9443ebadd49fa37055aea4.png" width="1107" />

5.长短链接

https://i-blog.csdnimg.cn/direct/6fded9eb810544aca5a31e56445f9e3e.png" width="516" />

https://i-blog.csdnimg.cn/direct/ff9dade0d30a4172a6cc68c4f56cb932.png" width="1200" />

https://i-blog.csdnimg.cn/direct/104a82cf0f454d3a86fde6ac9d146aa1.png" width="907" />

在 HTTP协议 中,长连接和短连接的概念主要体现在连接的持久性上。具体来说,HTTP协议的长短连接关系到客户端和服务器之间的连接是否保持持久,连接是否在多个请求之间复用。

http-10)">5.1 短连接(HTTP 1.0)

在HTTP/1.0中,默认情况下每个请求都建立一个新的连接,通信完成后连接就会立即关闭。这种方式被称为 短连接。每当客户端发起一个HTTP请求时,服务器会为这个请求创建一个新的TCP连接,并在响应发送完毕后立即关闭这个连接。对于每个请求和响应,都会有一次建立连接、传输数据和断开连接的过程。

短连接的特点:

  • 每个请求都需要建立新的TCP连接。
  • 每次请求响应后,连接都会被关闭。
  • 适用于请求量不大的场景,因为每次建立和断开连接会带来一定的性能开销。
C/C++ 中的短连接示例:

假设你使用C/C++编写一个HTTP客户端发起HTTP请求并接收响应:

#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>#define PORT 80int main() {int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0) {std::cerr << "Socket creation failed!" << std::endl;return -1;}sockaddr_in server_addr;server_addr.sin_family = AF_INET;server_addr.sin_port = htons(PORT);server_addr.sin_addr.s_addr = inet_addr("93.184.216.34");  // example.com IPif (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {std::cerr << "Connection failed!" << std::endl;return -1;}const char *request = "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n";send(sockfd, request, strlen(request), 0);char buffer[1024];int bytes_received = recv(sockfd, buffer, sizeof(buffer) - 1, 0);buffer[bytes_received] = '\0';std::cout << "Response:\n" << buffer << std::endl;close(sockfd);  // Connection is closed after responsereturn 0;
}

在这个短连接示例中,我们使用HTTP/1.0协议,每次请求完毕后,TCP连接会立即关闭。

http-11)">5.2 长连接(HTTP 1.1)

HTTP/1.1引入了 长连接(Keep-Alive) 的概念,在这种模式下,连接不会在每个请求后关闭,而是保持打开状态,可以复用相同的连接来处理多个请求。这意味着客户端和服务器之间的连接可以用于多个请求和响应,直到明确关闭连接。

默认情况下,HTTP/1.1会使用长连接,但可以通过设置请求头 Connection: close 来显式关闭连接。

长连接的特点:

  • 连接在多个请求/响应之间保持活跃。
  • 节省了每次请求建立和关闭连接的开销,适用于需要频繁通信的场景。
  • 服务器会在一定时间内保持连接,如果长时间没有请求,连接会被关闭。
C/C++ 中的长连接示例:
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>#define PORT 80int main() {int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0) {std::cerr << "Socket creation failed!" << std::endl;return -1;}sockaddr_in server_addr;server_addr.sin_family = AF_INET;server_addr.sin_port = htons(PORT);server_addr.sin_addr.s_addr = inet_addr("93.184.216.34");  // example.com IPif (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {std::cerr << "Connection failed!" << std::endl;return -1;}// Send multiple requests over the same connectionconst char *request1 = "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: keep-alive\r\n\r\n";send(sockfd, request1, strlen(request1), 0);char buffer[1024];int bytes_received = recv(sockfd, buffer, sizeof(buffer) - 1, 0);buffer[bytes_received] = '\0';std::cout << "Response 1:\n" << buffer << std::endl;const char *request2 = "GET /about HTTP/1.1\r\nHost: example.com\r\nConnection: keep-alive\r\n\r\n";send(sockfd, request2, strlen(request2), 0);bytes_received = recv(sockfd, buffer, sizeof(buffer) - 1, 0);buffer[bytes_received] = '\0';std::cout << "Response 2:\n" << buffer << std::endl;close(sockfd);  // Connection can be kept alive, but we close it herereturn 0;
}

在这个长连接的例子中,客户端向服务器发送两个HTTP请求,两个请求共享同一个TCP连接,直到手动关闭连接。通过在请求头中加入 Connection: keep-alive,客户端表明希望连接保持活跃。

5.3 关键区别总结

  • 短连接(HTTP/1.0):每个HTTP请求都建立一个新的TCP连接,通信结束后立即关闭,适用于请求量不大的情况。
  • 长连接(HTTP/1.1):连接在多个请求之间保持活跃,可以复用连接,直到服务器或客户端明确关闭连接,适用于需要频繁通信的场景。

5.4 长短连接的选择

  • 对于HTTP/1.0,通常使用短连接,尤其是在每个请求相对独立时。
  • 对于HTTP/1.1,长连接更为常见,尤其是在需要频繁请求或维持长期连接的场景(如实时应用、文件下载、网页加载等)。

长连接有助于减少连接的建立与关闭的开销,提高通信效率,尤其是在大量小请求的场景中,而短连接则适合一次性的请求和响应模式。

6.图片

https://i-blog.csdnimg.cn/direct/9310ab6054c444d39003ab38cdef9930.png" width="802" />

https://i-blog.csdnimg.cn/direct/5198db9e07f04a24a95504755a9ae42b.png" width="1200" />

https://i-blog.csdnimg.cn/direct/39782104236f4772948bc6bfde556b8c.png" width="1200" />

文件后缀

https://i-blog.csdnimg.cn/direct/e0460792ba2546e8a66cedfdb802b7d0.png" width="1143" />

7.cookie文件(记住密码)

文件级:可以记住一段时间

内存级:关闭就忘记

https://i-blog.csdnimg.cn/direct/b6ec584c85ba4e2aab622cdf0a1c9953.png" width="1200" />

8.HTTP协议

虽然我们说, 应用层协议是我们程序猿自己定的.

但实际上, 已经有大佬们定义了一些现成的, 又非常好用的应用层协议, 供我们直接参考使用. HTTP(超文本传输协议)

就是其中之一.

8.1 认识URL(网址)

平时我们俗称的 "网址" 其实就是说的 URL

https://i-blog.csdnimg.cn/direct/148406bbf2684d5fbb88e749adb99fe7.png" width="1110" />

8.2 urlencode和urldecode

像 / ? : 等这样的字符, 已经被url当做特殊意义理解了. 因此这些字符不能随意出现.

比如, 某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义.

转义的规则如下:

将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式

例如:

https://i-blog.csdnimg.cn/direct/cc548e6befce42408bfdb085eec2736b.png" width="923" />

"+" 被转义成了 "%2B" urldecode就是urlencode的逆过程;

工具:URL 编码和解码 - 在线 (urlencoder.org)

9.HTTP协议格式

HTTP请求

https://i-blog.csdnimg.cn/direct/e94d4d84b2274854a670424630bdd556.png" width="1200" />

  • 首行: [方法] + [url] + [版本]
  • Header: 请求的属性, 冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分结束
  • Body: 空行后面的内容都是Body. Body允许为空字符串. 如果Body存在, 则在Header中会有一个Content-Length属性来标识Body的长度;

HTTP响应

https://i-blog.csdnimg.cn/direct/9a6ffc6693e94826a61e8871f88750af.png" width="1200" />

  • 首行: [版本号] + [状态码] + [状态码解释]
  • Header: 请求的属性, 冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分结束
  • Body: 空行后面的内容都是Body. Body允许为空字符串. 如果Body存在, 则在Header中会有一个Content-Length属性来标识Body的长度; 如果服务器返回了一个html页面, 那么html页面内容就是在body中.

10.HTTP的方法

https://i-blog.csdnimg.cn/direct/633dc70725224d5f8c0d70549d6e0013.png" width="1200" />

其中最常用的就是GET方法和POST方法.

11.HTTP的状态码

https://i-blog.csdnimg.cn/direct/9f1dd53804624d0087a005bf3dabffd9.png" width="1200" />

最常见的状态码, 比如 200(OK), 404(Not Found), 403(Forbidden), 302(Redirect, 重定向), 504(Bad Gateway)

12.HTTP常见Header

  • Content-Type: 数据类型(text/html等)
  • Content-Length: Body的长度
  • Host: 客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上;
  • User-Agent: 声明用户的操作系统和浏览器版本信息;
  • referer: 当前页面是从哪个页面跳转过来的;
  • location: 搭配3xx状态码使用, 告诉客户端接下来要去哪里访问;
  • Cookie: 用于在客户端存储少量信息. 通常用于实现会话(session)的功能;

13.最简单的HTTP服务器

实现一个最简单的HTTP服务器, 只在网页上输出 "hello world"; 只要我们按照HTTP协议的要求构造数据, 就很容易 能做到;

https://i-blog.csdnimg.cn/direct/96ee63501a0d4fb9ad83841dd9279602.png" width="235" />

HttpServer.cc

#include "HttpServer.hpp"
#include<memory>
#include<iostream>using namespace std;
void Usage(const string& proc)
{cout<<"\nUsage" << proc << "port\n\n" <<endl;
}int main(int argc, char* argv[])
{if(argc != 2){Usage(argv[0]);exit(0);   }uint16_t port = stoi(argv[1]);unique_ptr<HttpServer> svr(new HttpServer(port));svr->Start();return 0;
}

HttpServer.hpp

#pragma once
#include <iostream>
#include <string>
#include <pthread.h>
#include <pthread.h>
#include <sstream>
#include <vector>
#include "Socket.hpp"
#include "logs/ljwlog.h"using namespace std;
static const int dafaultport = 8080;
const string wwwroot = "./wwwroot";//web根目录
const string sep = "\r\n";
//首页
const string homepage = "index.html";class ThreadData
{
public:ThreadData(int fd): sockfd(fd){}public:int sockfd;
};class HttpRequest
{
public://反序列化  这里把一个字符串变成多个字符串void Deserialize(string req){while(true){//找一行移动一行//                  分隔符size_t pos = req.find(sep);if(pos == string::npos){break;}string temp = req.substr(0, pos);//读到空行就直接跳出if(temp.empty()) break;req_header.push_back(temp);req.erase(0, pos + sep.size());}text = req;}void DebugPrint(){cout<<"-----------------------"<<endl;for(auto& line:req_header){cout<< line << "\n\n";}cout<< "method: " << method << endl;cout<< "url" << url <<endl;cout<< "http_version" << http_version <<endl;cout << text;}//解析第一行 vector 0号下标里的字符串void Parse(){stringstream ss(req_header[0]);ss >> method >> url >> http_version;file_path = wwwroot; //if(url == "/" || url == "/index.html"){file_path += "/";file_path += homepage;//    ./wwwroot/index.html}else{   file_path += url;// /a/b/c/d.html->./wwwroot/a/b/c/d.html   }}public:vector<string> req_header;//把每一行push到req_headerstring text;//正文//解析后的结果  vector 0号下标里的字符串string method;string url;string http_version;string file_path;
};class HttpServer
{
public:HttpServer(uint16_t port = dafaultport):port_(port){}bool Start(){listensock_.Socket();listensock_.Bind(port_);listensock_.Listen();for(;;){string clientip;uint16_t clientport;int sockfd = listensock_.Accept(&clientip, &clientport);if(sockfd < 0) continue;pthread_t tid;ThreadData *td = new ThreadData(sockfd);pthread_create(&tid, nullptr, ThreadRun, td);}}static string ReadHtmlContent(const string& htmlpath){ifstream in(htmlpath);if(!in.is_open()) return "404";string content;string line;while(getline(in, line)){content += line;}in.close();return content;}static void HandlerHttp(int sockfd){char buffer[10240];//跟read用法很像ssize_t n = recv(sockfd, buffer, sizeof(buffer), 0);if(n > 0){buffer[n] = 0;cout<< buffer; //假设我们读到的是一个完整的请求,独立的Http请求HttpRequest req;req.Deserialize(buffer);req.Parse();//解析//req.DebugPrint();// //返回相应的过程string text = ReadHtmlContent(req.file_path);string response_line = "HTTP/1.0 200 OK\r\n ";string response_header = "Content-Length ";response_header = to_string(text.size());response_header += "\r\n";string blank_line = "\r\n";string response = response_line;response += response_header;response += blank_line;response += text;//和write类似send(sockfd, response.c_str(), response.size(), 0);}close(sockfd);}//把收到的信息打印出来static void *ThreadRun(void *args){pthread_detach(pthread_self());ThreadData *td = static_cast<ThreadData*>(args);HandlerHttp(td->sockfd);delete td;return nullptr;}~HttpServer(){}
private:uint16_t port_;Sock listensock_;
};

makefile

httpServer:HttpServer.ccg++ -g -o $@ $^ -std=c++11 -lpthread
.PHONT:clean
clean:rm -f httpServer

Socket.hpp

#pragma once
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <cstring>
#include "./logs/ljwlog.h"using namespace std;enum
{SocketErr = 2,BindErr,ListenErr
};
const int backlog = 10;
class Sock
{
public:Sock(){}~Sock(){}public:void Socket() // 创建套接字的接口{sockfd_ = socket(AF_INET, SOCK_STREAM, 0); // 流式套接字  第二个参数是协议类型if (sockfd_ < 0){FATAL("Socket errno,error:%d,errstring:%s", errno, strerror(errno));exit(SocketErr);}}void Bind(uint16_t port) // 绑定的接口{struct sockaddr_in local;memset(&local, 0, sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(port);       // 主机转网络local.sin_addr.s_addr = INADDR_ANY; // ip默认0.0.0.0if (bind(sockfd_, (struct sockaddr *)&local, sizeof(local)) < 0){FATAL("Bind errno,error:%d,errstring:%s", errno, strerror(errno));exit(BindErr);}}void Listen() // 监听状态的接口{if (listen(sockfd_, backlog) < 0){FATAL("Listen errno,error:%d,errstring:%s", errno, strerror(errno));exit(ListenErr);}}//              知道谁链接的我int Accept(string *clientip, uint16_t *clientport) // 获取连接的接口{struct sockaddr_in peer; // 远端的意思socklen_t len = sizeof(peer);int newfd = accept(sockfd_, (struct sockaddr *)&peer, &len);if (newfd < 0){WARN("accept error, %s: %d", strerror(errno), errno);return -1;}// 网络转主机// 拿出客户端的ip和端口号char ipstr[64];inet_ntop(AF_INET, &peer.sin_addr, ipstr, sizeof(ipstr)); // 网络转主机*clientip = ipstr;                                        // 网络转主机*clientport = ntohs(peer.sin_port);                       // 网络转主机return newfd;}void Close(){close(sockfd_);}int Connect(const string &ip, const uint16_t &port) // 方便两个客户端和服务器都能使用这个Sock的这个公共方法{struct sockaddr_in peer;memset(&peer, 0, sizeof(peer));peer.sin_family = AF_INET;peer.sin_port = htons(port);inet_pton(AF_INET, ip.c_str(), &(peer.sin_addr));int n = connect(sockfd_, (struct sockaddr *)&peer, sizeof(peer));if (n == -1){cerr << "connect to" << ip << "::" << port <<"error"<< endl;return false;}return true;}int Fd(){return sockfd_;}private:int sockfd_;
};

wwwroot/a/b/hello.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" const="width=device-width,initial-scale=1.0"><title>Document</title>
</head>
<body><h1>第二个网页</h1><h1>第二个网页</h1><h1>第二个网页</h1><h1>第二个网页</h1><h1>第二个网页</h1><h1>第二个网页</h1>
</body>
</html>

wwwroot/image

https://i-blog.csdnimg.cn/direct/789619fec8e34f9796e2423646a0c67d.png" width="295" />

wwwroot/index.html

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" const="width=device-width,initial-scale=1.0"><title>Document</title>
</head><body><!-- <form action="/a/b/hello.html" method="post">name: <input type="text" name="name"><br>password: <input type="password" name="password"><br><input type="submit" value="提交"></form> --><h1>这是我们的首页</h1><img src="image/OIP-C.jpg" alt="这是一个咖啡"></body></html><!-- <!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" const="width=device-width,initial-scale=1.0"><title>Document</title>
</head>
<body><h1>hello world</h1><h1>hello world</h1><h1>hello world</h1><h1>hello world</h1><h1>hello world</h1><h1>hello world</h1><a href="https://blog.csdn.net/2401_83427936?spm=1000.2115.3001.5343">Ljw的博客链接</a><a href="https://101.34.66.193:8080/a/b/hello.html">第二个网页</a>
</body>
</html> -->

wwwroot/x/y/world.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" const="width=device-width,initial-scale=1.0"><title>Document</title>
</head>
<body><h1>第三个网页</h1><h1>第三个网页</h1><h1>第三个网页</h1><h1>第三个网页</h1><h1>第三个网页</h1><h1>第三个网页</h1>
</body>
</html>


http://www.ppmy.cn/devtools/138141.html

相关文章

亚马逊开发视频人工智能模型,The Information 报道

根据《The Information》周三的报道&#xff0c;电子商务巨头亚马逊&#xff08;AMZN&#xff09;已开发出一种新的生成式人工智能&#xff08;AI&#xff09;&#xff0c;不仅能处理文本&#xff0c;还能处理图片和视频&#xff0c;从而减少对人工智能初创公司Anthropic的依赖…

鸿蒙技术分享:Navigation页面管理-鸿蒙@fw/router框架源码解析(二)

theme: smartblue 本文是系列文章&#xff0c;其他文章见&#xff1a;鸿蒙fw/router框架源码解析&#xff08;一&#xff09;-Router页面管理 鸿蒙fw/router框架源码解析 介绍 fw/router是在HarmonyOS鸿蒙系统中开发应用所使用的开源模块化路由框架。该路由框架基于模块化开…

【第十课】Rust并发编程(一)

目录 前言 Fork和Join 前言 本节会介绍Rust中的并发编程&#xff0c;并发编程在编程中是提升cpu使用率的一大利器&#xff0c;通过多线程技术提升效率&#xff0c;Rust的并发和其他编程语言的并发不同的地方在于&#xff0c;Rust号称无畏并发。更重要的一点是安全。Rust中所有…

# issue 6 网络编程基础

一、网络的物理结构和光纤千兆网络 首先&#xff0c;我们需要知道网络的物理结构——数据是如何从一台机器传输到另外一台机器的 这个过程是非常重要的。现在很多人做软件开发&#xff0c;只会软件角度&#xff0c;这导致讲软件原理头头是道&#xff0c;但是连数据线都不会接&a…

基于OpenCV视觉库让机械手根据视觉判断物体有无和分类抓取的例程

项目实例&#xff0c;在一个无人封闭的隔绝场景中&#xff0c;根据视觉判断物件的有无&#xff0c;通过机械手 进行物件分类提取&#xff0c;并且返回状态结果&#xff1b; 实际的场景是有一个类似采血的固件支架盘&#xff0c;上面很多采血管&#xff0c;采血管帽颜色可能不同…

深入探索Flax:一个用于构建神经网络的灵活和高效库

深入探索Flax&#xff1a;一个用于构建神经网络的灵活和高效库 在深度学习领域&#xff0c;TensorFlow 和 PyTorch 作为主流的框架&#xff0c;已被广泛使用。不过&#xff0c;Flax 作为一个较新的库&#xff0c;近年来得到了越来越多的关注。Flax 是一个由Google Research团队…

租赁小程序|租赁系统搭建|租赁系统需求

随着信息技术的高速发展&#xff0c;租赁行业逐渐向智能化、便捷化方向迈进。一款优秀的租赁小程序&#xff0c;旨在为用户提供一站式的租赁服务体验&#xff0c;同时帮助租赁企业优化管理流程&#xff0c;提高业务效率。 一、用户需求精准把握 在开发任何软件产品时&#xff0…

2024年11月28日Github流行趋势

项目名称&#xff1a;OpenInterpreter 项目维护者&#xff1a;KillianLucas, Notnaton, MikeBirdTech, CyanideByte, ericrallen项目介绍&#xff1a;一个自然语言计算机接口&#xff0c;允许用户通过自然语言与计算机交互。项目star数&#xff1a;56,695项目fork数&#xff1a…