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

相关推荐
zhangjw345 小时前
Java基础语法:变量、数据类型与运算符,从原理到实战
java·开发语言
yaoxin5211238 小时前
384. Java IO API - Java 文件复制工具:Copy 示例完整解析
java·开发语言·python
NotFound4868 小时前
实战指南如何实现Java Web 拦截机制:Filter 与 Interceptor 深度分享
java·开发语言·前端
Ava的硅谷新视界9 小时前
用了一天 Claude Opus 4.7,聊几点真实感受
开发语言·后端·编程
rabbit_pro9 小时前
Python调用onnx模型
开发语言·python
AC赳赳老秦9 小时前
OpenClaw生成博客封面图+标题,适配CSDN视觉搜索,提升点击量
运维·人工智能·python·自动化·php·deepseek·openclaw
浪客川10 小时前
【百例RUST - 010】字符串
开发语言·后端·rust
向宇it11 小时前
php高性能的导出excel读写扩展——xlswriter,比传统的Spreadsheet要快很多
php·excel·xlswriter
赵侃侃爱分享11 小时前
学完Python第一次写程序写了这个简单的计算器
开发语言·python
断眉的派大星11 小时前
# Python 魔术方法(魔法方法)超详细讲解
开发语言·python