无法连接到在 Docker 容器中运行的 SCTP 服务器。

huangapple go评论68阅读模式
英文:

unable to connect to sctp server running in docker container

问题

我正在尝试使用以下Docker文件将SCTP服务器容器化:

FROM ubuntu:20.04

# 安装工具
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"]

一旦Docker容器开始运行,我从主机向在Docker中运行的SCTP服务器发送了客户端请求,但我在客户端上遇到了超时。在tcpdump中看不到任何数据包到达服务器。

以下是主机上的一些命令输出:

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

./client
Enter data to send: abc
Connection failed
connect(): Connection timed out

-- 主机上的netstat显示连接已关闭

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?

这是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 /* 这可以根据需要更改,并且应该与服务器和客户端中的端口号相同 */

int main()
{
  // 服务器代码在这里
}

这是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 /* 这可以根据需要更改,并且应该与服务器和客户端中的端口号相同 */

int main(int argc, char* argv[])
{
  // 客户端代码在这里
}

这些是您提供的代码和输出的部分翻译。如果您需要更多帮助或有其他问题,请随时提问。

英文:

I am trying to containerize an SCTP server with below docker file

FROM  ubuntu:20.04

# Install utilities
RUN apt update &amp;&amp; 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 [&quot;./server&quot;]

Once docker container start running. I send a client request from my host machine to the sctp server running in docker.
But I get timeout on client. No pkt reaches to server as seen in tcpdump.

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

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

-- netstat on host shows closed connection

/home/ubuntu&gt;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 -&gt; why client connect is closed? 
/home/ubuntu&gt;

sctp server code

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;unistd.h&gt;
#include &lt;time.h&gt;
#include &lt;sys/socket.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;netinet/in.h&gt;
#include &lt;netinet/sctp.h&gt;
#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(&quot;Failed to create socket\n&quot;);
      perror(&quot;socket()&quot;);
      exit(1);
  }

  bzero ((void *) &amp;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 *) &amp;servaddr, sizeof (servaddr));

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

  /* Specify that a maximum of 5 streams will be available per socket */
  memset (&amp;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,
      &amp;initmsg, sizeof (initmsg));

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

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

  while (1)
    {

      char buffer[MAX_BUFFER + 1];
      int len;

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

      printf (&quot;Awaiting a new connection\n&quot;);

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

      in = sctp_recvmsg (connSock, buffer, sizeof (buffer), (struct sockaddr *) NULL, 0, &amp;sndrcvinfo, &amp;flags);
      if( in == -1)
      {
          printf(&quot;Error in sctp_recvmsg\n&quot;);
          perror(&quot;sctp_recvmsg()&quot;);
          close(connSock);
          continue;
      }
      else
      {
          //Add &#39;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;unistd.h&gt;
#include &lt;time.h&gt;
#include &lt;sys/socket.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;netinet/in.h&gt;
#include &lt;netinet/sctp.h&gt;
#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(&quot;Failed to create socket\n&quot;);
perror(&quot;socket()&quot;);
exit(1);
}
bzero ((void *) &amp;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 *) &amp;servaddr, sizeof (servaddr));
if(ret == -1 )
{
printf(&quot;Bind failed \n&quot;);
perror(&quot;bind()&quot;);
close(listenSock);
exit(1);
}
/* Specify that a maximum of 5 streams will be available per socket */
memset (&amp;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,
&amp;initmsg, sizeof (initmsg));
if(ret == -1 )
{
printf(&quot;setsockopt() failed \n&quot;);
perror(&quot;setsockopt()&quot;);
close(listenSock);
exit(1);
}
ret = listen (listenSock, 5);
if(ret == -1 )
{
printf(&quot;listen() failed \n&quot;);
perror(&quot;listen()&quot;);
close(listenSock);
exit(1);
}
while (1)
{
char buffer[MAX_BUFFER + 1];
int len;
//Clear the buffer
bzero (buffer, MAX_BUFFER + 1);
printf (&quot;Awaiting a new connection\n&quot;);
connSock = accept (listenSock, (struct sockaddr *) NULL, (int *) NULL);
if (connSock == -1)
{
printf(&quot;accept() failed\n&quot;);
perror(&quot;accept()&quot;);
close(connSock);
continue;
} else {
printf (&quot;New client connected....\n&quot;);
}
in = sctp_recvmsg (connSock, buffer, sizeof (buffer), (struct sockaddr *) NULL, 0, &amp;sndrcvinfo, &amp;flags);
if( in == -1)
{
printf(&quot;Error in sctp_recvmsg\n&quot;);
perror(&quot;sctp_recvmsg()&quot;);
close(connSock);
continue;
}
else
{
//Add &#39;\0&#39; in case of text data
buffer[in] = &#39;\0&#39;;
printf (&quot; Length of Data received: %d\n&quot;, in);
printf (&quot; Data : %s\n&quot;, (char *) buffer);
}
close (connSock);
}
return 0;
}
&#39; in case of text data buffer[in] = &#39;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;unistd.h&gt;
#include &lt;time.h&gt;
#include &lt;sys/socket.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;netinet/in.h&gt;
#include &lt;netinet/sctp.h&gt;
#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(&quot;Failed to create socket\n&quot;);
perror(&quot;socket()&quot;);
exit(1);
}
bzero ((void *) &amp;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 *) &amp;servaddr, sizeof (servaddr));
if(ret == -1 )
{
printf(&quot;Bind failed \n&quot;);
perror(&quot;bind()&quot;);
close(listenSock);
exit(1);
}
/* Specify that a maximum of 5 streams will be available per socket */
memset (&amp;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,
&amp;initmsg, sizeof (initmsg));
if(ret == -1 )
{
printf(&quot;setsockopt() failed \n&quot;);
perror(&quot;setsockopt()&quot;);
close(listenSock);
exit(1);
}
ret = listen (listenSock, 5);
if(ret == -1 )
{
printf(&quot;listen() failed \n&quot;);
perror(&quot;listen()&quot;);
close(listenSock);
exit(1);
}
while (1)
{
char buffer[MAX_BUFFER + 1];
int len;
//Clear the buffer
bzero (buffer, MAX_BUFFER + 1);
printf (&quot;Awaiting a new connection\n&quot;);
connSock = accept (listenSock, (struct sockaddr *) NULL, (int *) NULL);
if (connSock == -1)
{
printf(&quot;accept() failed\n&quot;);
perror(&quot;accept()&quot;);
close(connSock);
continue;
} else {
printf (&quot;New client connected....\n&quot;);
}
in = sctp_recvmsg (connSock, buffer, sizeof (buffer), (struct sockaddr *) NULL, 0, &amp;sndrcvinfo, &amp;flags);
if( in == -1)
{
printf(&quot;Error in sctp_recvmsg\n&quot;);
perror(&quot;sctp_recvmsg()&quot;);
close(connSock);
continue;
}
else
{
//Add &#39;\0&#39; in case of text data
buffer[in] = &#39;\0&#39;;
printf (&quot; Length of Data received: %d\n&quot;, in);
printf (&quot; Data : %s\n&quot;, (char *) buffer);
}
close (connSock);
}
return 0;
}
&#39;; printf (&quot; Length of Data received: %d\n&quot;, in); printf (&quot; Data : %s\n&quot;, (char *) buffer); } close (connSock); } return 0; }

sctp client code

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;unistd.h&gt;
#include &lt;sys/socket.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;netinet/in.h&gt;
#include &lt;netinet/sctp.h&gt;
#include &lt;arpa/inet.h&gt;
#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(&quot;Enter data to send: &quot;);
  fgets(buffer, MAX_BUFFER, stdin);
  /* Clear the newline or carriage return from the end*/
  buffer[strcspn(buffer, &quot;\r\n&quot;)] = 0;
  /* Sample input */
  //strncpy (buffer, &quot;Hello Server&quot;, 12);
  //buffer[12] = &#39;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;unistd.h&gt;
#include &lt;sys/socket.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;netinet/in.h&gt;
#include &lt;netinet/sctp.h&gt;
#include &lt;arpa/inet.h&gt;
#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(&quot;Enter data to send: &quot;);
fgets(buffer, MAX_BUFFER, stdin);
/* Clear the newline or carriage return from the end*/
buffer[strcspn(buffer, &quot;\r\n&quot;)] = 0;
/* Sample input */
//strncpy (buffer, &quot;Hello Server&quot;, 12);
//buffer[12] = &#39;\0&#39;;
datalen = strlen(buffer);
connSock = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
if (connSock == -1)
{
printf(&quot;Socket creation failed\n&quot;);
perror(&quot;socket()&quot;);
exit(1);
}
bzero ((void *) &amp;servaddr, sizeof (servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons (MY_PORT_NUM);
servaddr.sin_addr.s_addr = inet_addr (&quot;127.0.0.1&quot;);
ret = connect (connSock, (struct sockaddr *) &amp;servaddr, sizeof (servaddr));
if (ret == -1)
{
printf(&quot;Connection failed\n&quot;);
perror(&quot;connect()&quot;);
close(connSock);
exit(1);
}
ret = sctp_sendmsg(connSock, (void *) buffer, (size_t) datalen, NULL, 0, 0, 0, 0, 0, 0);
if(ret == -1 )
{
printf(&quot;Error in sctp_sendmsg\n&quot;);
perror(&quot;sctp_sendmsg()&quot;);
} else {
printf(&quot;Successfully sent %d bytes data to server\n&quot;, ret);
}
close (connSock);
return 0;
}
&#39;; datalen = strlen(buffer); connSock = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP); if (connSock == -1) { printf(&quot;Socket creation failed\n&quot;); perror(&quot;socket()&quot;); exit(1); } bzero ((void *) &amp;servaddr, sizeof (servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons (MY_PORT_NUM); servaddr.sin_addr.s_addr = inet_addr (&quot;127.0.0.1&quot;); ret = connect (connSock, (struct sockaddr *) &amp;servaddr, sizeof (servaddr)); if (ret == -1) { printf(&quot;Connection failed\n&quot;); perror(&quot;connect()&quot;); close(connSock); exit(1); } ret = sctp_sendmsg(connSock, (void *) buffer, (size_t) datalen, NULL, 0, 0, 0, 0, 0, 0); if(ret == -1 ) { printf(&quot;Error in sctp_sendmsg\n&quot;); perror(&quot;sctp_sendmsg()&quot;); } else { printf(&quot;Successfully sent %d bytes data to server\n&quot;, ret); } close (connSock); return 0; }

答案1

得分: 0

我通过执行这里描述的步骤成功修复了它:https://stackoverflow.com/questions/57963675/sctp-connections-between-docker-containers-hangs

在运行 Docker 容器时,我忽略了 Docker 的主机网络选项。

sudo docker run --net=host --name learnsha-pr -d -p 62324:62324/sctp learnsha

正如上述帖子所提到的,Docker 中的 SCTP 支持仍然很原始。

英文:

I managed to fix it by doing the steps described here: https://stackoverflow.com/questions/57963675/sctp-connections-between-docker-containers-hangs

I was missing docker's host networking option while running the docker container.

sudo docker run --net=host --name learnsha-pr -d -p 62324:62324/sctp learnsha

SCTP support is still primitive in docker, as per the above-mentioned thread.

huangapple
  • 本文由 发表于 2023年3月7日 20:35:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/75662044.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定