C++怎么实现简单套接字Socket_C++服务端代码编写【实战】

0次阅读

Address already in use 错误应先查杀残留进程,再设 SO_REUSEADDR;backlog 需显式设为 1024 或 SOMAXCONN;recv() 返回 0 表示对端关闭,需主动 close()。

C++ 怎么实现简单套接字 Socket_C++ 服务端代码编写【实战】

bind() 失败提示 Address already in use 怎么办

端口被占是服务端启动失败最常见原因,不是代码写错了,而是上次进程没彻底退出,或者系统还没回收连接状态。

  • 先用 netstat -tuln | grep :<your_port></your_port>lsof -i :<your_port></your_port> 查端口谁在用
  • 启动前加 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))opt = 1,避免 TIME_WAIT 卡住端口
  • SO_REUSEPORT 在 Linux 3.9+ 也支持,但多进程复用时才需要,单服务端用 SO_REUSEADDR 就够了
  • 别一看到报错就改端口号——掩盖问题不如清掉残留进程:kill $(lsof -t -i :<your_port>)</your_port>

accept() 阻塞住,客户端连不上?检查 listen() 参数

listen() 的第二个参数是 backlog,它不是“最大并发数”,而是内核里已完成三次握手、但还没被 accept() 取走的连接队列长度。设太小会导致 SYN 收到后直接丢包,客户端超时或重传失败。

  • Linux 默认 backlog 是 128,但很多发行版实际限制更严(如 systemd 会截断),建议显式设为 1024SOMAXCONN
  • 如果客户端反复显示 Connection refused,先确认服务端是否真执行到了 listen() 之后——加个 printf("listening on %dn", port) 看输出
  • 防火墙和 SELinux 也可能拦截:临时关掉测试:sudo systemctl stop firewalld(仅调试)

recv() 返回 0 不代表出错,而是对端 close() 了

C++ 里没有“连接已断开”的异常抛出,所有状态都靠返回值判断。很多人把 recv() 返回 0 当成错误处理,结果逻辑跳过清理,导致 fd 泄漏或后续读写崩溃。

  • recv() 返回 -1 才要查 errno:比如 EAGAIN(非阻塞模式下无数据)、ECONNRESET(对方 RST 断连)
  • 返回 0 表示对端调用了 close()shutdown(SHUT_WR),该连接进入半关闭状态,你该 close() 自己这端了
  • 别在循环里只写 if (n ——漏掉了 <code>n == 0 的语义,应明确区分:if (n == 0) {/* 对端关闭 */} else if (n

struct sockaddr_in 初始化不全,bind() 随机绑定到奇怪端口

忘记清零结构体,sin_portsin_addr 里是栈上脏数据,bind() 可能成功但监听在不可预期的地址或端口,客户端连不上还查不出原因。

立即学习 C++ 免费学习笔记(深入)”;

  • 必须初始化:struct sockaddr_in addr{};(C++11 起支持聚合初始化清零)或用 memset(&addr, 0, sizeof(addr))
  • htons() 必须用:端口号要转网络字节序,addr.sin_port = htons(8080),写 8080 直接赋值是错的
  • addr.sin_family = AF_INET 不能漏,否则可能匹配到 IPv6 套接字行为,尤其在 dual-stack 系统上表现诡异

实际跑通一个最小服务端,核心就四步:socket()bind()listen()accept() 循环。难点不在语法,而在每个系统调用返回后你有没有真正看懂它想告诉你什么。特别是 errno 和返回值组合,比任何文档都真实。

星耀云
版权声明:本站原创文章,由 星耀云 2026-03-12发表,共计1527字。
转载说明:转载本网站任何内容,请按照转载方式正确书写本站原文地址。本站提供的一切软件、教程和内容信息仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。
text=ZqhQzanResources