SCTP多宿主
|
我一直在开发这个简单的客户端-使用C的服务器应用程序,其中客户端只是向服务器发送随机数据,而服务器只是侦听客户端发送的内容。我使用的协议是SCTP,我对如何对其实现多宿主功能感兴趣。
我一直在互联网上搜索有关SCTP和多宿主的信息,但还没有找到有关如何指示SCTP使用多个地址进行通信的示例。我仅设法找到了尝试使用多宿主设置SCTP时应使用的命令,它应该非常简单。
我创建了一个客户端和一个服务器,它们都使用我的计算机的两个WLAN接口作为它们的连接点。两个适配器都连接到同一AP。服务器正在从这些接口监听来自客户端的数据,并且客户端通过它们发送数据。问题是,当我断开客户端向其发送数据的主WLAN适配器的连接时,传输应在回退到辅助连接时暂停。我已经使用Wireshark跟踪了数据包,并且第一个INIT和INIT_ACK数据包报告客户端和服务器都使用WLAN适配器作为它们的通信链接。
当我重新连接主要的WLAN连接后,传输会在一段时间后继续,并突然将大量数据包发送到服务器,这是不对的。数据包应该已经通过辅助连接传输了。在许多站点上,据说SCTP会自动在连接之间切换,但是在我看来,这并没有发生。那么,你们有什么线索,即使客户端和服务器知道彼此的地址(包括辅助地址)时,当主链路断开时,为什么传输也不会回退到辅助连接?
关于服务器:
服务器创建一个SOCK_SEQPACKET类型的套接字,并绑定与INADDR_ANY找到的所有接口。 getladdrs报告服务器已绑定到3个地址(包括127.0.0.1)。之后,服务器侦听套接字,并等待客户端发送数据。服务器通过sctp_recvmsg调用读取数据。
关于客户:
客户端还会创建一个SEQPACKET套接字,并连接到命令行参数指定的IP地址。在这种情况下,getladdrs还返回3个地址,例如在服务器情况下。之后,客户端将开始向服务器发送数据,并延迟一秒钟,直到用户使用Ctrl-C中断发送。
这是一些源代码:
服务器:
#define BUFFER_SIZE (1 << 16)
#define PORT 10000
int sock, ret, flags;
int i;
int addr_count = 0;
char buffer[BUFFER_SIZE];
socklen_t from_len;
struct sockaddr_in addr;
struct sockaddr_in *laddr[10];
struct sockaddr_in *paddrs[10];
struct sctp_sndrcvinfo sinfo;
struct sctp_event_subscribe event;
struct sctp_prim prim_addr;
struct sctp_paddrparams heartbeat;
struct sigaction sig_handler;
void handle_signal(int signum);
int main(void)
{
if((sock = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP)) < 0)
perror(\"socket\");
memset(&addr, 0, sizeof(struct sockaddr_in));
memset((void*)&event, 1, sizeof(struct sctp_event_subscribe));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(PORT);
from_len = (socklen_t)sizeof(struct sockaddr_in);
sig_handler.sa_handler = handle_signal;
sig_handler.sa_flags = 0;
if(sigaction(SIGINT, &sig_handler, NULL) == -1)
perror(\"sigaction\");
if(setsockopt(sock, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe)) < 0)
perror(\"setsockopt\");
if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int))< 0)
perror(\"setsockopt\");
if(bind(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr)) < 0)
perror(\"bind\");
if(listen(sock, 2) < 0)
perror(\"listen\");
addr_count = sctp_getladdrs(sock, 0, (struct sockaddr**)laddr);
printf(\"Addresses binded: %d\\n\", addr_count);
for(i = 0; i < addr_count; i++)
printf(\"Address %d: %s:%d\\n\", i +1, inet_ntoa((*laddr)[i].sin_addr), (*laddr)[i].sin_port);
sctp_freeladdrs((struct sockaddr*)*laddr);
while(1)
{
flags = 0;
ret = sctp_recvmsg(sock, buffer, BUFFER_SIZE, (struct sockaddr*)&addr, &from_len, NULL, &flags);
if(flags & MSG_NOTIFICATION)
printf(\"Notification received from %s:%u\\n\", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
printf(\"%d bytes received from %s:%u\\n\", ret, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
}
if(close(sock) < 0)
perror(\"close\");
}
void handle_signal(int signum)
{
switch(signum)
{
case SIGINT:
if(close(sock) != 0)
perror(\"close\");
exit(0);
break;
default: exit(0);
break;
}
}
和客户:
#define PORT 10000
#define MSG_SIZE 1000
#define NUMBER_OF_MESSAGES 1000
#define PPID 1234
int sock;
struct sockaddr_in *paddrs[10];
struct sockaddr_in *laddrs[10];
void handle_signal(int signum);
int main(int argc, char **argv)
{
int i;
int counter = 1;
int ret;
int addr_count;
char address[16];
char buffer[MSG_SIZE];
sctp_assoc_t id;
struct sockaddr_in addr;
struct sctp_status status;
struct sctp_initmsg initmsg;
struct sctp_event_subscribe events;
struct sigaction sig_handler;
memset((void*)&buffer, \'j\', MSG_SIZE);
memset((void*)&initmsg, 0, sizeof(initmsg));
memset((void*)&addr, 0, sizeof(struct sockaddr_in));
memset((void*)&events, 1, sizeof(struct sctp_event_subscribe));
if(argc != 2 || (inet_addr(argv[1]) == -1))
{
puts(\"Usage: client [IP ADDRESS in form xxx.xxx.xxx.xxx] \");
return 0;
}
strncpy(address, argv[1], 15);
address[15] = 0;
addr.sin_family = AF_INET;
inet_aton(address, &(addr.sin_addr));
addr.sin_port = htons(PORT);
initmsg.sinit_num_ostreams = 2;
initmsg.sinit_max_instreams = 2;
initmsg.sinit_max_attempts = 5;
sig_handler.sa_handler = handle_signal;
sig_handler.sa_flags = 0;
if(sigaction(SIGINT, &sig_handler, NULL) == -1)
perror(\"sigaction\");
if((sock = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP)) < 0)
perror(\"socket\");
if((setsockopt(sock, SOL_SCTP, SCTP_INITMSG, &initmsg, sizeof(initmsg))) != 0)
perror(\"setsockopt\");
if((setsockopt(sock, SOL_SCTP, SCTP_EVENTS, (const void *)&events, sizeof(events))) != 0)
perror(\"setsockopt\");
if(sendto(sock, buffer, MSG_SIZE, 0, (struct sockaddr*)&addr, sizeof(struct sockaddr)) == -1)
perror(\"sendto\");
addr_count = sctp_getpaddrs(sock, 0, (struct sockaddr**)paddrs);
printf(\"\\nPeer addresses: %d\\n\", addr_count);
for(i = 0; i < addr_count; i++)
printf(\"Address %d: %s:%d\\n\", i +1, inet_ntoa((*paddrs)[i].sin_addr), (*paddrs)[i].sin_port);
sctp_freepaddrs((struct sockaddr*)*paddrs);
addr_count = sctp_getladdrs(sock, 0, (struct sockaddr**)laddrs);
printf(\"\\nLocal addresses: %d\\n\", addr_count);
for(i = 0; i < addr_count; i++)
printf(\"Address %d: %s:%d\\n\", i +1, inet_ntoa((*laddrs)[i].sin_addr), (*laddrs)[i].sin_port);
sctp_freeladdrs((struct sockaddr*)*laddrs);
i = sizeof(status);
if((ret = getsockopt(sock, SOL_SCTP, SCTP_STATUS, &status, (socklen_t *)&i)) != 0)
perror(\"getsockopt\");
printf(\"\\nSCTP Status:\\n--------\\n\");
printf(\"assoc id = %d\\n\", status.sstat_assoc_id);
printf(\"state = %d\\n\", status.sstat_state);
printf(\"instrms = %d\\n\", status.sstat_instrms);
printf(\"outstrms = %d\\n--------\\n\\n\", status.sstat_outstrms);
for(i = 0; i < NUMBER_OF_MESSAGES; i++)
{
counter++;
printf(\"Sending data chunk #%d...\", counter);
if((ret = sendto(sock, buffer, MSG_SIZE, 0, (struct sockaddr*)&addr, sizeof(struct sockaddr))) == -1)
perror(\"sendto\");
printf(\"Sent %d bytes to peer\\n\",ret);
sleep(1);
}
if(close(sock) != 0)
perror(\"close\");
}
void handle_signal(int signum)
{
switch(signum)
{
case SIGINT:
if(close(sock) != 0)
perror(\"close\");
exit(0);
break;
default: exit(0);
break;
}
}
你们知道我在做什么错吗?
没有找到相关结果
已邀请:
3 个回复
橙绥
客户:
嗜蒂谷尘旱
卧沫
请注意,
与您的
不同 当你做
它似乎打开了一对多样式的套接字,我不知道它是否支持多宿主。 因此,请尝试使用
参数进行编码。 这也是使用
的示例。