当前位置: 首页 > news >正文

Linux网络编程基础-简易TCP服务器框架

1. 引入头文件

#include<iostream>        
#include<sys/types.h>     // 系统数据类型(如 pid_t、size_t)
#include<sys/socket.h>    // socket 函数及数据结构(socket(), bind(), listen() 等)
#include<netinet/in.h>    // sockaddr_in 结构体定义,IPV4 地址
#include<arpa/inet.h>     // IP 地址转换函数(inet_pton)
#include<signal.h>        // 信号处理(signal())
#include<unistd.h>        // POSIX 系统调用,如 close(), sleep()
#include<stdlib.h>        // 标准库函数,如 atoi()
#include<assert.h>        // assert() 断言函数,用于调试
#include<string.h>        // 字符串函数,如 bzero()

2. 全局变量与信号处理

static bool stop = false; // 全局标志变量,控制主循环是否退出

handle_term(int sig):信号处理函数

static void handle_term(int sig)
{stop = true;
}
  • 参数 sig 是信号编号(比如 SIGTERM 对应 15)。
  • 这个函数的作用是:当接收到某个信号(如 kill -15)时,把 stop 设置为 true,让主循环停止。

3. 主函数部分

函数声明和参数

int main(int argc, char* argv[])
  • argc:命令行参数个数(包括程序本身)
  • argv[]:命令行参数数组(argv[0] 是程序名)

例如运行:

./myserver 127.0.0.1 8888 5
  • argc = 4
  • argv[1] = "127.0.0.1"
  • argv[2] = "8888"
  • argv[3] = "5"

注册信号处理函数

signal(SIGTERM, handle_term);
  • 作用:当收到 SIGTERM 信号(编号 15)时,调用 handle_term()
  • 实现优雅关闭服务器(如用户 kill 程序时能正常释放资源)

检查参数是否合法

if(argc <= 3)
{std::cout << "usage: " << basename(argv[0]) << " ip_address port_number backlog" << std::endl;return 1;
}
  • 如果参数不足,输出用法提示并退出。

  • basename(argv[0]) 返回程序名(不含路径)

  • 示例输出:

    usage: myserver 127.0.0.1 8888 5
    

解析命令行参数

const char* ip = argv[1];        // 获取 IP 字符串
int port = atoi(argv[2]);        // 将字符串转为 int 类型的端口号
int backlog = atoi(argv[3]);     // 将字符串转为 int 类型的连接队列大小
  • atoi()(ASCII to int)将字符串转换为整数
  • backlog 控制的是 listen() 函数中最多能有多少个“未accept的连接”排队

创建 socket 套接字

int sock = socket(PF_INET, SOCK_STREAM, 0);
assert(sock >= 0);
socket() 参数解释:
int socket(int domain, int type, int protocol);
参数含义
domainPF_INET使用 IPv4 协议族(也可写 AF_INET,等价)
typeSOCK_STREAM表示使用 TCP(面向连接)
protocol0默认协议(TCP 默认就是 0)
  • 成功返回 socket 文件描述符(int 型)
  • assert() 确保创建成功,否则程序直接崩溃(用于调试)

创建并初始化地址结构

struct sockaddr_in address;
bzero(&address, sizeof(address));    // 将地址结构全部清零
address.sin_family = AF_INET;        // 协议族:IPv4
inet_pton(AF_INET, ip, &address.sin_addr); // 将 IP 字符串转为网络字节序整数
address.sin_port = htons(port);      // 将主机字节序转为网络字节序
说明:
  • sockaddr_in 是用于 IPv4 的 socket 地址结构。

  • bzero()memset(&address, 0, sizeof(address)) 的简化版,作用是清空结构体。

  • inet_pton(AF_INET, ip, &address.sin_addr)

    • 将 IP 地址字符串(如 “127.0.0.1”)转为网络字节序(用于通信)
  • htons(port)

    • 将主机字节序的端口号转为网络字节序(统一使用大端)

绑定地址

int ret = bind(sock, (struct sockaddr*)&address, sizeof(address));
assert(ret != -1);
bind() 参数:
int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
  • sockfd:socket 描述符
  • addr:地址结构(需要强转为 sockaddr*
  • addrlen:地址结构大小

作用:把 socket 绑定到你指定的本地地址(IP + 端口号)


开始监听连接

ret = listen(sock, backlog);
assert(ret != -1);
listen() 参数:
int listen(int sockfd, int backlog);
  • sockfd:socket 描述符
  • backlog:等待连接的队列长度(最大连接排队数)

作用:把 socket 变为监听状态,准备接受客户端连接


主循环逻辑(等待 SIGTERM)

while(!stop)
{sleep(1);
}
  • 死循环中每秒 sleep 一下(CPU 负载低)
  • 一旦收到 SIGTERM(stop == true),跳出循环
  • 注意这里没有真正处理任何连接,只是为了演示信号控制退出流程

程序清理和退出

close(sock);
return 0;
  • close(sock):关闭 socket,释放资源
  • return 0:正常退出程序

总结:完整程序做了什么?

步骤作用
创建 socket建立 TCP 套接字
设置地址结构设置 IP、端口
bind把 socket 绑定到地址
listen开始监听
signal 注册收到信号时修改 stop 标志
while 循环不断 sleep,等待信号中断
close收到信号后关闭 socket,退出程序

测试

在这里插入图片描述
在这里插入图片描述

http://www.xdnf.cn/news/1249345.html

相关文章:

  • 大前端游戏应用中 AI 角色行为智能控制
  • 网站、域名、IP在什么场景下需要备案
  • Fabric.js从入门学习到实现labelImg矩形多边形标注工具【上】
  • SmartMediaKit 模块化音视频框架实战指南:场景链路 + 能力矩阵全解析
  • ICCV 2025 | 视频生成迈入“多段一致”新时代!TokensGen用“压缩Token”玩转长视频生成
  • GPU 优化-用 tensor core实现5G Massive MIMO 64x64
  • Linux系统之Docker命令与镜像、容器管理
  • nginx代理出https,request.getRequestURL()得到http问题解决
  • imx6ull-驱动开发篇10——pinctrl 子系统
  • 福彩双色球第2025090期篮球号码分析
  • 生成式 AI 重塑自动驾驶仿真:4D 场景生成技术的突破与实践
  • Spring之【初识AOP】
  • Agent安全机制:权限控制与风险防范
  • 海康威视相机,MVS连接成功,但无图像怎么办?
  • 云计算一阶段Ⅱ——12. SELinux 加固 Linux 安全
  • 统计鱼儿分布情况 Java
  • libpq库使用
  • 二叉树算法
  • Mysql常用语句
  • Bilateral Reference for High-Resolution Dichotomous Image Segmentation
  • 智慧社区(八)——社区人脸识别出入管理系统设计与实现
  • 轻量应用服务器Centos系统上安装jdk8和Jdk17教程(详细)
  • (ZipList入门笔记二)为何ZipList可以实现内存压缩,可以详细介绍一下吗
  • 在AI时代,如何制定有效的职业规划?AI时代职业规划+AI产品经理角色
  • 探索设计模式的宝库:Java-Design-Patterns
  • FastDeploy2.0:报qwen2.embed_tokens.weight
  • 3. 为什么 0.1 + 0.2 != 0.3
  • 多传感器融合
  • Redis之Set和SortedSet类型常用命令
  • leetcode-python-删除链表的倒数第 N 个结点