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)的基础,也是开发实际网络应用(聊天室、文件传输、远程控制等)的必备技能。

相关推荐
渡我白衣13 分钟前
深入理解 Transformer:Transformer 究竟是什么?
java·linux·开发语言·c++·人工智能·深度学习·transformer
「QT(C++)开发工程师」8 小时前
C++ 11 常用for循环
开发语言·c++
我还记得那天8 小时前
0 初识C++
开发语言·c++
FfHUCisI9 小时前
Go 编译过程全景
开发语言·后端·golang
FfHUCisI9 小时前
Golang 语法分析与 AST:Parser 与 go/ast
开发语言·后端·golang
lemon_sjdk10 小时前
ObjectProperty
java·开发语言·算法
大模型码小白10 小时前
Spring AI Tool 实现自然语言操作 MySQL 数据库详解
服务器·开发语言·数据库·人工智能·python·mysql·spring
hh95010 小时前
Agent Plan x DeepSeek Harness:Agent 供应链安全与第三方插件审计
java·开发语言·安全·agent plan·adg成都社区·adg社区
「QT(C++)开发工程师」10 小时前
C++ std::move 详解
开发语言·c++