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,退出程序

测试

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

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值