You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

编写C客户端向TCP服务器发送TCP RST包遇异常,求技术排查

为什么我的C客户端程序没有发送TCP RST包?

你的代码目前不会发送TCP RST包,因为默认情况下调用close()会触发TCP的优雅关闭流程(发送FIN包),而不是强制重置连接(发送RST包)。要主动发送RST,你需要修改套接字的SO_LINGER选项,让内核在关闭套接字时直接终止连接。

问题根源

当你调用close()时,TCP协议会先尝试发送所有已缓冲的数据,然后向对方发送FIN包,等待对方的ACK和FIN回应,完成四次挥手。这是正常的关闭流程,不会产生RST。

修改方案:设置SO_LINGER选项

通过设置SO_LINGER选项,指定当关闭套接字时,如果还有未处理的连接数据,直接发送RST包终止连接。具体需要将struct linger的l_onoff设为1,l_linger设为0。

修改后的代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <sys/socket.h> // 新增头文件,用于SO_LINGER相关定义

int main() {
  int sock = socket(AF_INET, SOCK_STREAM, 0);
  if (sock == -1) {
    perror("Socket creation failed");
    exit(EXIT_FAILURE);
  }

  // 配置SO_LINGER选项,触发RST包发送
  struct linger l_opt;
  l_opt.l_onoff = 1;    // 启用linger功能
  l_opt.l_linger = 0;   // 延迟时间设为0,直接发送RST终止连接
  if (setsockopt(sock, SOL_SOCKET, SO_LINGER, &l_opt, sizeof(l_opt)) == -1) {
    perror("setsockopt SO_LINGER failed");
    close(sock);
    exit(EXIT_FAILURE);
  }

  struct sockaddr_in server_addr;
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
  server_addr.sin_port = htons(8080);

  if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) != 0) {
    perror("Connection failed");
    exit(EXIT_FAILURE);
  }

  // 此时关闭套接字会直接发送RST包
  close(sock);

  return 0;
}

注意事项

  • 设置SO_LINGER为0后,关闭套接字时会直接丢弃未发送的数据,强制发送RST,对方会收到"连接重置"的错误。
  • 必须包含<sys/socket.h>头文件,否则struct linger和setsockopt可能无法正常编译。
  • 这种方式仅适用于模拟异常断开的场景,正常业务场景应优先使用优雅关闭(shutdown() + close())。

内容的提问来源于stack exchange,提问作者Carla

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 21:57:51