英文:
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 && 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"]
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>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 on host shows closed connection
/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 server code
#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 '#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;
}
' in case of text data
buffer[in] = '#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;
}
';
printf (" Length of Data received: %d\n", in);
printf (" Data : %s\n", (char *) buffer);
}
close (connSock);
}
return 0;
}
sctp client code
#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] = '#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;
}
';
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;
}
答案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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论