TCP 网络编程学习笔记

一、常见踩坑点

现象 原因 解决方法
编译时 undefined reference to ... 未链接必要的库(如 -lts 对于 tslib,但 TCP 编程无需额外库) TCP 编程一般只需 gcc 直接编译,若使用 pthread 等需加 -lpthread
运行客户端时提示 Usage: ./client <server_ip> 未提供 IP 地址参数 运行:./client 127.0.0.1
服务器 bind error: Address already in use 端口被占用,可能是上一个服务器进程未退出,或处于 TIME_WAIT 状态 1. 用 pkill server 杀掉旧进程 2. 使用 setsockopt 设置 SO_REUSEADDR 选项
客户端 connect error 服务器未运行,或 IP 地址错误,或防火墙阻止 确保服务器已启动,IP 正确,尝试 ping 测试连通性
服务器子进程变成僵尸(<defunct> 父进程未回收子进程资源 在服务器开头添加 signal(SIGCHLD, SIG_IGN); 让系统自动回收
客户端输入 exit 后服务器没反应 客户端发送的字符串包含换行符 \n,而服务器用 strcmp 比较时未去除 在客户端用 strcspn 或手动去掉换行符;或在服务器接收后也去掉换行符
服务器打印乱码或额外字符 接收到的数据未以 \0 结尾,直接打印 recv 后加上 ucRecvBuf[iRecvLen] = '\0';
第二个客户端无法连接/通信 服务器未使用并发(fork/线程),主进程阻塞在第一个客户端的 recv 使用 fork 创建子进程处理每个客户端,或用 select/poll 实现 I/O 多路复用
客户端正常退出,但服务器端 recv 未返回 0 客户端未正确关闭 socket(如只 exit 未调用 close 在客户端 break 前调用 close(iSocketClient);
服务器端打印的客户端编号始终是 0 或 -1 忘记在每次 accept 后递增 iClientNum,或未正确传递 accept 成功后 iClientNum++,子进程中应使用该编号(注意子进程复制了父进程变量)

二、核心概念总结

1. TCP 编程基本步骤

服务器端

  1. socket() -- 创建监听 socket

  2. bind() -- 绑定 IP 和端口

  3. listen() -- 开始监听

  4. accept() -- 等待客户端连接,返回新的通信 socket

  5. recv() / send() -- 与客户端通信

  6. close() -- 关闭 socket

客户端

  1. socket() -- 创建 socket

  2. connect() -- 连接服务器

  3. send() / recv() -- 通信

  4. close() -- 关闭

2. 并发处理

  • 使用 fork() 为每个客户端创建一个子进程,父进程继续等待新连接。

  • 子进程处理完通信后必须退出(returnexit),避免成为僵尸。

  • 使用 signal(SIGCHLD, SIG_IGN) 让系统自动回收子进程资源,避免僵尸进程。

3. 优雅关闭连接

  • 应用层可以约定特殊命令(如 exit)作为断开信号。

  • 发送 exit 后,客户端主动关闭 socket。

  • 服务器端收到 exitrecv 返回 0,也应关闭 socket 并退出子进程。

4. 字符串协议注意事项

  • 网络传输的是字节流,没有自动的字符串结束符。

  • 接收后必须手动添加 \0 才能作为 C 字符串处理。

  • 使用 fgets 时会保留换行符,需去除后再比较(或用 strncmp 指定长度)。

5. 阻塞 I/O 的影响

  • 默认情况下,acceptrecvsend 等函数会阻塞直到操作完成。

  • 单进程服务器如果阻塞在一个客户端的 recv 上,将无法接受新连接或处理其他客户端。

  • 解决方案:多进程、多线程、非阻塞 I/O、I/O 多路复用(select/poll/epoll)。


三、学习收获

通过本次学习,你掌握了:

  • TCP 套接字编程的核心函数和流程。

  • 如何使用 fork 实现简单的并发服务器。

  • 如何自定义应用层协议(如退出命令)实现优雅关闭。

  • 常见错误的排查方法(端口占用、僵尸进程、字符串处理等)。

  • 通过修改代码、观察现象加深了对阻塞、并发等概念的理解。

这些知识是后续学习更高级网络编程(如 epoll、多线程、异步 I/O)的基础,也是开发实际网络应用(聊天室、文件传输、远程控制等)的必备技能。

相关推荐
计算机毕设定制辅导-无忧学长17 分钟前
《基于SpringBoot的未成年人健康知识科普平台的设计与实现》
java·开发语言·vue.js·spring boot·未成年人健康知识科普平台
Ivanqhz32 分钟前
Ping-Pong 双缓冲
开发语言·人工智能·python·深度学习·mlir
m0_7345717635 分钟前
深入理解C++ RAII
开发语言·c++
泡海椒38 分钟前
jquick-pdf 表格实战:动态数据 PDF 报表生成
java·开发语言·pdf
aramae1 小时前
模拟实现memset()(C语言)
c语言·开发语言·后端
wuyk5551 小时前
【Socket 进阶之路】第 7 章 IO 多路复用 select & poll 完整实战|多 fd 监听、超时等待、优缺点横向对比
服务器·开发语言·网络·数据库·物联网
船厂电气自动化ai大模型1 小时前
AI大模型与数学|第81天 课程:正交向量、正交基、格拉姆‑施密特(Gram‑Schmidt)正交化
开发语言·数据结构·人工智能·线性代数·机器学习
lv__pf2 小时前
seata【实战 msb】
java·开发语言·后端
点纭2 小时前
C 语言 第七章 常用函数(3)
c语言·开发语言·算法·oracle·c#
右耳朵猫AI2 小时前
PHP周刊2026W38 | Laravel AI可观测、Symfony三版本、Webhook零信任、事件溯源架构
后端·php·laravel