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

相关推荐
minglie14 小时前
lean4环境安装
开发语言·前端
chh5634 小时前
从零开始学习C++ -- 基础知识
开发语言·c++·windows·学习·算法
Lzh编程小栈4 小时前
【数据结构与算法】C语言实现双向链表 (Double Linked List) 全解析
c语言·开发语言·数据结构·链表
heimeiyingwang4 小时前
【架构实战】系统设计面试题精选
java·开发语言·架构
Ulyanov4 小时前
基于ttk的Python现代化GUI开发指南
开发语言·前端·python·tkinter·系统设计
枫叶丹44 小时前
【HarmonyOS 6.0】Telephony Kit 新能力:精准获取卡槽ID与SIM卡对应关系
开发语言·华为·harmonyos
不会写DN4 小时前
PHP mysqli 实用开发指南
android·开发语言·php
Evand J4 小时前
【MATLAB例程】多无人机协同巡逻仿真:基于长机-僚机模型的编队保持与串级PID控制
开发语言·matlab·无人机·控制·pid·串级pid
yoothey4 小时前
我对Java Web开发中多线程的困惑
java·开发语言·前端