UNIX网络编程笔记:TCP客户/服务器程序示例

服务器实例

有个著名的项目,tiny web,本项目将其改到windows下,并使用RAII重构,编写过程中对于内存泄漏确实很头疼,还没写完,后面会继续更:

#include <iostream>
#include <vector>
#include <stdexcept>
#include <string>
#include<ranges>
#include<format>
#include <stdio.h>
#include <WinSock2.h>
#include <Windows.h>
#pragma comment(lib, "WS2_32.lib")class WSAInitializer {
public:WSAInitializer() {WSADATA data;int ret = WSAStartup(MAKEWORD(2, 2), &data);if (ret != 0) {throw std::runtime_error("WSAStartup failed. Error code: " + std::to_string(ret));}}~WSAInitializer() {WSACleanup();}WSAInitializer(const WSAInitializer&) = delete;WSAInitializer& operator=(const WSAInitializer&) = delete;
};class Socket {
public:Socket() = default;Socket(int domain, int type, int protocol) {sock_ = socket(domain, type, protocol);if (sock_ == INVALID_SOCKET) {throw std::runtime_error("Socket creation failed. Error code: " + std::to_string(WSAGetLastError()));}}explicit Socket(SOCKET s) : sock_(s) {}~Socket() {if (sock_ != INVALID_SOCKET) {closesocket(sock_);}}Socket(Socket&& other) noexcept : sock_(other.sock_) {other.sock_ = INVALID_SOCKET;}Socket& operator=(Socket&& other) noexcept {if (this != &other) {closesocket(sock_);sock_ = other.sock_;other.sock_ = INVALID_SOCKET;}return *this;}SOCKET get() const { return sock_; }operator SOCKET() const { return sock_; }Socket(const Socket&) = delete;Socket& operator=(const Socket&) = delete;
private:SOCKET sock_ = INVALID_SOCKET;
};Socket startup(unsigned short* port) {Socket server_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);int opt = 1;if (setsockopt(server_socket.get(), SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char*>(&opt), sizeof(opt)) == SOCKET_ERROR) {throw std::runtime_error("setsockopt failed. Error code: " + std::to_string(WSAGetLastError()));}sockaddr_in server_addr = {};server_addr.sin_family = AF_INET;server_addr.sin_port = htons(*port);server_addr.sin_addr.s_addr = htonl(INADDR_ANY);if (bind(server_socket.get(), reinterpret_cast<const sockaddr*>(&server_addr), sizeof(server_addr)) == SOCKET_ERROR) {throw std::runtime_error("bind failed. Error code: " + std::to_string(WSAGetLastError()));}if (*port == 0) {sockaddr_in name;int nameLen = sizeof(name);if (getsockname(server_socket.get(), reinterpret_cast<sockaddr*>(&name), &nameLen) == SOCKET_ERROR) {throw std::runtime_error("getsockname failed. Error code: " + std::to_string(WSAGetLastError()));}*port = ntohs(name.sin_port);}if (listen(server_socket.get(), 5) == SOCKET_ERROR) {throw std::runtime_error("listen failed. Error code: " + std::to_string(WSAGetLastError()));}return server_socket;
}int get_line(SOCKET sock, std::vector<char>& buff, int size) {buff.resize(size);char c = 0;int i = 0;while (i < size - 1 && c != '\n') {int n = recv(sock, &c, 1, 0);if (n > 0) {if (c == '\r') {n = recv(sock, &c, 1, MSG_PEEK);if (n > 0 && c == '\n') {recv(sock, &c, 1, 0);} else {c = '\n';}}buff[i++] = c;} else {c = '\n';}}buff[i] = '\0';return i;
}void unimplemented(SOCKET client) {const char* response = "HTTP/1.1 501 Not Implemented\r\n""Content-Type: text/html\r\n""\r\n""<html><head><title>Not Implemented</title></head>""<body><h1>501 Not Implemented</h1></body></html>";send(client, response, strlen(response), 0);
}DWORD WINAPI accept_request(LPVOID arg) {std::unique_ptr<Socket> client_socket(static_cast<Socket*>(arg));SOCKET client = client_socket->get();std::vector<char> buff(1024);int numchars = get_line(client, buff, buff.size());// 示例:解析请求方法char method[255] = {0};int i = 0, j = 0;while (!isspace(buff[j]) && i < sizeof(method) - 1) {method[i++] = buff[j++];}// 示例:检查支持的HTTP方法if (_stricmp(method, "GET") && _stricmp(method, "POST")) {unimplemented(client);return 0;}// 示例:解析URL(简化版)std::vector<char> url(255, 0);i = 0;while (isspace(buff[j]) && j < buff.size()) j++;while (!isspace(buff[j]) && i < url.size() - 1 && j < buff.size()) {url[i++] = buff[j++];}// 示例:发送响应(实际应处理请求)const char* response = "HTTP/1.1 200 OK\r\n""Content-Type: text/html\r\n""\r\n""<html><head><title>Test</title></head>""<body><h1>Hello World</h1></body></html>";send(client, response, strlen(response), 0);return 0;
}int main() {try {WSAInitializer wsa;unsigned short port = 8880;Socket server_socket = startup(&port);std::cout << "Server started on port " << port << std::endl;while (true) {sockaddr_in client_addr;int addr_len = sizeof(client_addr);SOCKET client_sock = accept(server_socket.get(), reinterpret_cast<sockaddr*>(&client_addr), &addr_len);if (client_sock == INVALID_SOCKET) {throw std::runtime_error("accept failed. Error code: " + std::to_string(WSAGetLastError()));}Socket* client_socket = new Socket(client_sock);HANDLE hThread = CreateThread(nullptr, 0, accept_request, client_socket, 0, nullptr);if (!hThread) {delete client_socket;throw std::runtime_error("CreateThread failed. Error code: " + std::to_string(GetLastError()));}CloseHandle(hThread);}} catch (const std::exception& e) {std::cerr << "Error: " << e.what() << std::endl;return 1;}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/74201.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI Agent开发大全第四课-提示语工程:从简单命令到AI对话的“魔法”公式

什么是提示语工程&#xff1f;一个让AI“听话”的秘密 如果你曾经尝试过用ChatGPT或者其他大语言模型完成任务&#xff0c;那么你一定遇到过这样的情况&#xff1a;明明你的问题是清晰的&#xff0c;但答案却离题万里&#xff1b;或者你认为自己提供的信息足够详尽&#xff0c…

系统架构设计知识体系总结

1.技术选型 1.什么是技术选型&#xff1f; 技术选型是指评估和选择在项目或系统开发中使用的最合适的技术和工具的过程。这涉及考虑基于其能力、特性、与项目需求的兼容性、可扩展性、性能、维护和其他因素的各种可用选项。技术选型的目标是确定与项目目标相符合、能够有效解…

基于3DMax与Vray引擎的轻量级室内场景渲染实践

欢迎踏入3DMAX室内渲染的沉浸式学习之旅!在这个精心设计的实战教程中,我们将携手揭开3DMAX与Vray这对黄金搭档在打造现实室内场景时的核心奥秘。无论您是渴望入门的3D新手,还是追求极致效果的专业设计师,这里都将为您呈现从场景蓝图构建到光影魔法施加的完整技术图谱。我们…

逻辑卷,vdo,(阿里加速器)

一、逻辑卷 10 20 30 1.逻辑卷的2个特点 &#xff08;1&#xff09;逻辑卷可以将多个分区或者磁盘整合成一个更大的逻辑磁盘&#xff0c;然后可以从逻辑磁盘上划分出分区&#xff08;逻辑磁盘的大小等于整合的物理磁盘大小之和。&#xff09; &#xff08;2&#xff09;能…

检索增强生成(2)本地PDF 本地嵌入模型

from langchain_community.document_loaders import PyPDFLoader from pathlib import Pathdef load_local_pdf(file_path):if not Path(file_path).exists():raise FileNotFoundError(f"文件 {file_path} 不存在&#xff01;")loader PyPDFLoader(file_path)try:do…

安全守护:反光衣检测技术的革新之路

视觉分析助力船上工人反光衣检测 在现代工业生产与作业环境中&#xff0c;安全始终是首要考虑的因素。对于水上作业&#xff0c;如船舶维护、海上施工等场景&#xff0c;工人穿戴反光衣是预防事故、提高可见性的重要措施。然而&#xff0c;传统的人工检查方式不仅效率低下&…

【Scrapy】Scrapy教程8——处理子链接

通过前面几篇文章,已经了解了如何去爬取网页内容并存储到数据库,但是目前只是存储了一个页面的内容,现在想要获取每篇文章链接内的文章内容,我们来看看怎么获取。 生成新请求 首先我们肯定要先拿到链接,所以第一步都获取文章标题和链接肯定少不了,然后再爬取获取到到子…

Centos6配置yum源

Centos6配置yum源 为Centos6配置CentOS Vault源—防止yum源过期为Centos6配置epel源为Centos6配置ELRepo源---已ELRepo被官方清空Centos6安装dockerdocker配置国内镜像加速 为Centos6配置CentOS Vault源—防止yum源过期 参考&#xff1a;https://mirrors.ustc.edu.cn/help/cen…

“智改数转”新风口,物联网如何重构制造业竞争力?

一、政策背景 为深化制造业智能化改造、数字化转型、网络化联接&#xff0c;江苏省制定了《江苏省深化制造业智能化改造数字化转型网络化联接三年行动计划&#xff08;2025&#xff0d;2027年&#xff09;》&#xff0c;提出到2027年&#xff0c;全省制造业企业设备更新、工艺…

制作Oracle11g Docker 镜像

基于Linux系统&#xff0c;宿主主机要设置如下环境变量&#xff0c;oracle为64位版本 dockerfile中需要的数据库安装包可从csdn下载内找到 #!/bin/bash # 在宿主机上运行以设置Oracle所需的内核参数 # 这些命令需要root权限cat > /etc/sysctl.d/99-oracle.conf << EO…

从GTC2025首次量子日看英伟达量子AI融合算力网络前景与趋势

GTC2025 Quantum Day 最新内容全部汇总: 技术名称描述合作伙伴/开发者应用场景/目标量子模拟器优化方案NVIDIA与IonQ、D-Wave合作,针对量子模拟器进行性能优化,提升量子计算任务效率。IonQ、D-Wave量子算法开发、复杂系统模拟混合量子-经典计算架构结合量子计算与经典GPU加速…

UE4学习笔记 FPS游戏制作12 添加第二把枪,制作枪的父类,动态生成物体,切换武器

我们添加一个发射器类型的枪 我们目前有了一个Rifle的枪械蓝图&#xff0c;我们在添加Launcher时&#xff0c;需要为他们添加一个父类&#xff0c;将公共方法放到父类里&#xff0c;方法体由子类实现 添加父类 方法1 新建一个Gun的蓝图&#xff0c;Gun继承Actor&#xff0c;…

【原创首发】开源基于AT32 SIP/VOIP电话

前言 本次为了反馈各位粉丝的关注&#xff0c;特此分享 AT32_VOIP 工程&#xff0c;此功能其实跟我之前发过的《STM32F429的VOIP功能》是一样的&#xff0c;只是用了AT32F437。 其实那个工程是一个比较Demo中的Demo&#xff0c;很多功能和硬件依赖性太大了。后面项目中发现AT…

通俗易懂搞懂@RequestParam 和 @RequestBody

&#x1f4cc; 博主简介: &#x1f4bb; 努力学习的 23 级科班生一枚 &#x1f680;&#x1f3e0; 博主主页 &#xff1a; &#x1f4ce; 灰阳阳&#x1f4da; 往期回顾 &#xff1a;Session和Cookie我不允许你不懂&#x1f4ac; 每日一言&#xff1a; 「流水不争先&#xff0c…

dubbo版本与分组

Dubbo服务中&#xff0c;接口并不能唯一确定一个服务&#xff0c;只有 接口分组版本号 的三元组才能唯一确定一个服务。 当同一个接口针对不同的业务场景、不同的使用需求或者不同的功能模块等场景&#xff0c;可使用服务分组来区分不同的实现方式。同时&#xff0c;这些不同实…

RAG现有技术方案

RAG现有技术方案 一、现有技术方案的核心问题 检索质量不足 挑战:传统RAG系统依赖单轮检索,难以应对智能电网的海量异构数据(如传感器读数、控制参数),导致检索结果相关性低、覆盖不全。案例:BM25稀疏检索在处理长文本或专业术语时,易遗漏语义关联;BGE等稠密检索模型对…

redis MISCONF Redis is configured to save RDB snapshots报错解决

直接上解决方案 修改redis配置文件 stop-writes-on-bgsave-error no 重启redis

个人学习编程(3-22) leetcode刷题

连续子数组&#xff1a;&#xff08;难&#xff09; 示例 1: 输入: nums [0,1] 输出: 2 说明: [0, 1] 是具有相同数量 0 和 1 的最长连续子数组。 示例 2: 输入: nums [0,1,0] 输出: 2 说明: [0, 1] (或 [1, 0]) 是具有相同数量0和1的最长连续子数组。 需要理解的知识&a…

希尔排序

希尔排序是一种改进的插入排序算法&#xff0c;它通过将原始数据分成多个子序列来改善插入排序的性能&#xff0c;每个子序列的元素间隔为 d&#xff08;增量&#xff09;。随着算法的进行&#xff0c;d 逐渐减小&#xff0c;最终减为 1&#xff0c;此时整个序列就被排序好了。…

JavaScript基础-DOM事件流

在Web开发过程中&#xff0c;理解和掌握DOM事件流是实现高效交互的关键。DOM事件流描述了当一个事件发生时&#xff0c;它在文档树中的传播路径。了解事件流的概念有助于我们更精确地控制事件处理逻辑&#xff0c;避免不必要的行为&#xff0c;并提升用户体验。本文将深入探讨D…