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

无法连接Docker容器中运行的SCTP服务器问题求助

SCTP服务器容器化后连接超时问题排查

问题背景

使用Dockerfile将SCTP服务器容器化后,宿主机客户端向容器内服务器发送请求时出现连接超时,tcpdump显示无数据包到达服务器。

Dockerfile

FROM  ubuntu:20.04

# Install utilities
RUN apt update && apt install -y libsctp-dev iputils-ping  net-tools curl gcc tcpdump vim

RUN mkdir -p /root/my_proj/
COPY . /root/my_proj/

WORKDIR /root/my_proj/
RUN   gcc sctpserver.c -o server -lsctp

CMD ["./server"]

相关命令输出

容器状态

/home/ubuntu>sudo docker ps -a | grep sha
f99817f89f26   learnsha     "./server"     59 minutes ago   Up 59 minutes   0.0.0.0:62324->62324/sctp, :::62324->62324/sctp   learnsha-pr

客户端运行结果

/home/ubuntu>./client 
Enter data to send: abc                           --------> client is hung on host machine
Connection failed
connect(): Connection timed out

宿主机netstat输出

/home/ubuntu>netstat -n |  grep 62324
sctp                :::62324                           LISTEN     
sctp                0.0.0.0:62324                      LISTEN     
sctp       0      0 127.0.0.1:50638  127.0.0.1:62324   CLOSE -> why client connect is closed? 
/home/ubuntu>

代码实现

SCTP服务器代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#define MAX_BUFFER 1024
#define MY_PORT_NUM 62324 /* This can be changed to suit the need and should be same in server and client */

int
main ()
{
  int listenSock, connSock, ret, in, flags, i;
  struct sockaddr_in servaddr;
  struct sctp_initmsg initmsg;
  struct sctp_event_subscribe events;
  struct sctp_sndrcvinfo sndrcvinfo;
  char buffer[MAX_BUFFER + 1];

  listenSock = socket (AF_INET, SOCK_STREAM, IPPROTO_SCTP);
  if(listenSock == -1)
  {
      printf("Failed to create socket\n");
      perror("socket()");
      exit(1);
  }

  bzero ((void *) &servaddr, sizeof (servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_addr.s_addr = htonl (INADDR_ANY);
  servaddr.sin_port = htons (MY_PORT_NUM);

  ret = bind (listenSock, (struct sockaddr *) &servaddr, sizeof (servaddr));

  if(ret == -1 )
  {
      printf("Bind failed \n");
      perror("bind()");
      close(listenSock);
      exit(1);
  }

  /* Specify that a maximum of 5 streams will be available per socket */
  memset (&initmsg, 0, sizeof (initmsg));
  initmsg.sinit_num_ostreams = 5;
  initmsg.sinit_max_instreams = 5;
  initmsg.sinit_max_attempts = 4;
  ret = setsockopt (listenSock, IPPROTO_SCTP, SCTP_INITMSG,
      &initmsg, sizeof (initmsg));

  if(ret == -1 )
  {
      printf("setsockopt() failed \n");
      perror("setsockopt()");
      close(listenSock);
      exit(1);
  }

  ret = listen (listenSock, 5);
  if(ret == -1 )
  {
      printf("listen() failed \n");
      perror("listen()");
      close(listenSock);
      exit(1);
  }

  while (1)
    {

      char buffer[MAX_BUFFER + 1];
      int len;

      //Clear the buffer
      bzero (buffer, MAX_BUFFER + 1);

      printf ("Awaiting a new connection\n");

      connSock = accept (listenSock, (struct sockaddr *) NULL, (int *) NULL);
      if (connSock == -1)
      {
        printf("accept() failed\n");
        perror("accept()");
        close(connSock);
        continue;
      } else {
         printf ("New client connected....\n");
      }

      in = sctp_recvmsg (connSock, buffer, sizeof (buffer), (struct sockaddr *) NULL, 0, &sndrcvinfo, &flags);
      if( in == -1)
      {
          printf("Error in sctp_recvmsg\n");
          perror("sctp_recvmsg()");
          close(connSock);
          continue;
      }
      else
      {
          //Add '\0' in case of text data
          buffer[in] = '\0';

          printf (" Length of Data received: %d\n", in);
          printf (" Data : %s\n", (char *) buffer);
      }
      close (connSock);
    }

  return 0;
}

SCTP客户端代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <arpa/inet.h>
#define MAX_BUFFER 1024
#define MY_PORT_NUM 62324 /* This can be changed to suit the need and should be same in server and client */

int
main (int argc, char* argv[])
{
  int connSock, in, i, ret, flags;
  struct sockaddr_in servaddr;
  struct sctp_status status;
  char buffer[MAX_BUFFER + 1];
  int datalen = 0;

  /*Get the input from user*/
  printf("Enter data to send: ");
  fgets(buffer, MAX_BUFFER, stdin);
  /* Clear the newline or carriage return from the end*/
  buffer[strcspn(buffer, "\r\n")] = 0;
  /* Sample input */
  //strncpy (buffer, "Hello Server", 12);
  //buffer[12] = '\0';
  datalen = strlen(buffer);

  connSock = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
  if (connSock == -1)
  {
      printf("Socket creation failed\n");
      perror("socket()");
      exit(1);
  }

  bzero ((void *) &servaddr, sizeof (servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons (MY_PORT_NUM);
  servaddr.sin_addr.s_addr = inet_addr ("127.0.0.1");

  ret = connect (connSock, (struct sockaddr *) &servaddr, sizeof (servaddr));
  if (ret == -1)
  {
      printf("Connection failed\n");
      perror("connect()");
      close(connSock);
      exit(1);
  }

  ret = sctp_sendmsg(connSock, (void *) buffer, (size_t) datalen, NULL, 0, 0, 0, 0, 0, 0);
  if(ret == -1 )
  {
    printf("Error in sctp_sendmsg\n");
    perror("sctp_sendmsg()");
  } else {
      printf("Successfully sent %d bytes data to server\n", ret);
  }

  close (connSock);
  return 0;
}

排查方向

  • 检查宿主机SCTP模块加载状态:执行lsmod | grep sctp,若未加载则运行modprobe sctp启用模块,SCTP依赖内核模块支持,未加载会导致数据包无法处理。
  • 验证容器内服务器监听状态:进入容器执行ss -anp | grep sctp或netstat -n | grep 62324,确认服务器进程是否真的在监听62324端口的SCTP套接字。
  • 检查Docker网络对SCTP的支持:Docker 1.12及以上版本支持SCTP,但需宿主机内核支持。启动容器时尝试添加--cap-add NET_ADMIN权限,部分环境下SCTP转发需要额外权限。
  • 排查防火墙/iptables规则:检查宿主机iptables是否有阻止SCTP数据包的规则,执行iptables -L -n | grep sctp查看相关规则,必要时添加允许SCTP流量的规则。
  • 测试容器内本地连接:在容器内部编译运行客户端,连接127.0.0.1:62324,确认服务器本身功能正常,排除代码逻辑问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 08:27:05