HTTP

server/2025/2/24 8:56:36/

目录

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" name="tableOfContents" style="margin-left:40px">5.1 短连接(HTTP 1.0)

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

http-11)-toc" name="tableOfContents" 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)" name="1-短连接(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)" name="2-长连接(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/server/170304.html

相关文章

广东英语十二种应用文模版范文

1. 邀请信&#xff08;Invitation Letter&#xff09; 模版 Dear [Recipients Name],I hope this letter finds you well. I am writing to invite you to [Event Name] which will be held on [Date] at [Location]. The event will start at [Time] and we would be deligh…

从硬件工程师视角解析宇树机器人:四足机器人的核心设计与技术挑战

——以Unitree Go1为例&#xff0c;探索四足机器人硬件设计的奥秘 近年来&#xff0c;四足机器人凭借其灵活的运动能力和广泛的场景适应性&#xff0c;成为机器人领域的热门方向。国内企业宇树科技&#xff08;Unitree Robotics&#xff09;凭借Unitree Go1、B1等产品迅速崛起…

服务器通过 ollama 运行deepseek r1

1、服务器环境简介 56核 CPU64G 内存无显卡已安装 Ollama 2、下载模型与配置 正常可以通过 ollama pull 或 ollama run 命令直接下载&#xff0c;但通常会遇到连接超时、找不到网址等总理。因此&#xff0c;可以使用国内的模型站进行下载&#xff0c;在这里使用魔塔查找模型…

【网络编程】UNIX 域套接字(Unix Domain Sockets, UDS)

UNIX 域套接字 UNIX 域套接字&#xff08;UDS, Unix Domain Socket&#xff09;是一种 本地进程间通信&#xff08;IPC&#xff09; 方式&#xff0c;适用于同一台机器上的进程之间的通信。相比 TCP/IP 套接字&#xff0c;UDS 效率更高、延迟更低&#xff0c;因为它省去了网络…

RabbitMQ 消息队列

1. 消息队列是什么&#xff1f; 当用户注册成功后&#xff0c;就发送邮件。当邮件发送成功了&#xff0c;接口才会提示注册成功信息。但由于发送邮件&#xff0c;依赖于其他厂商的服务&#xff0c;有可能他们的接口会非常耗时。那么用户就一直要等着邮件发送成功了&#xff0c;…

Linux系统编程基础详解

Linux 系统详解 大纲 引言 Linux 的定义Linux 的历史与发展本文结构概述 Linux 的基本概念 Linux 的架构 内核与用户空间系统调用 Linux 的文件系统 文件与目录结构权限管理 Linux 的进程管理 进程与线程进程调度 Linux 的基本命令与操作 常用命令概述 文件与目录操作命令文…

20250223下载并制作RTX2080Ti显卡的显存的测试工具mats

20250223下载并制作RTX2080Ti显卡的显存的测试工具mats 2025/2/23 23:23 缘起&#xff1a;我使用X99的主板&#xff0c;使用二手的RTX2080Ti显卡【显存22GB版本&#xff0c;准备学习AI的】 但是半年后发现看大码率的视频容易花屏&#xff0c;最初以为是WIN10经常更换显卡/来回更…

单链表:数据结构中的灵活“链条”

目录 &#x1f680;前言&#x1f914;单链表是什么&#xff1f;&#x1f4af;单链表的结构特点&#x1f4af;单链表的用途 ✍️单链表的实现与接口解释&#x1f4af;打印链表&#x1f4af;尾插操作&#x1f4af;头插操作&#x1f4af;头删操作&#x1f4af;尾删操作&#x1f4a…