C - 使用select在多个端口上侦听的简单ipv6 udp服务器。从一个端口接收消息,而不是另一个
这是我的代码。C - 使用select在多个端口上侦听的简单ipv6 udp服务器。从一个端口接收消息,而不是另一个
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <stdio.h>
#include <string.h>
int max(int socket_handle[]);
int main(void)
{
int max_clients_allowed = 2;
int socket_handle[max_clients_allowed];
int client_handle[max_clients_allowed];
struct sockaddr_in6 server_address[max_clients_allowed];
struct sockaddr_in6 client_address[max_clients_allowed];
char buffer[1000];
socklen_t client_length;
fd_set read_handles;
struct timeval timeout_interval;
int bytes_received;
int port_number = 9000;
int retval;
int i;
printf("Hello, human.\n");
for (i = 0; i < max_clients_allowed; i++)
{
printf("Creating socket%d on port: %d\n", i, port_number + i);
socket_handle[i] = socket(PF_INET6,SOCK_DGRAM,0);
memset(&server_address[i], 0, sizeof(server_address[i]));
server_address[i].sin6_family = AF_INET6;
server_address[i].sin6_addr=in6addr_any;
server_address[i].sin6_port=htons(port_number + i);
if(bind(socket_handle[i], (struct sockaddr *)&server_address[i], sizeof(server_address[i])) < 0)
{
perror("Unable to bind.");
return -1;
}
else
{
printf("Bind %d successful.\n", i);
}
}
while (1) {
FD_ZERO(&read_handles);
FD_SET(socket_handle[0], &read_handles);
FD_SET(socket_handle[1], &read_handles);
timeout_interval.tv_sec = 2;
timeout_interval.tv_usec = 500000;
retval = select(max(socket_handle) + 1, &read_handles, NULL, NULL, &timeout_interval);
if (retval == -1)
{
printf("Select error\n");
//error
}
else if ((retval = 0))
{
printf("timeout\n");
}
else
{
//good
client_length = sizeof(struct sockaddr*);
for (i = 0; i < max_clients_allowed; i++)
{
if (FD_ISSET(socket_handle[i], &read_handles))
{
if((bytes_received = recvfrom(socket_handle[i],buffer,sizeof(buffer),0,(struct sockaddr *)&client_address[i], (socklen_t*)&client_length)) < 0)
{
perror("Error in recvfrom.");
break;
}
printf("\nData received:");
printf("\n--------------\n");
printf("%s", buffer);
}
}
}
}
}
int max(int socket_handle[])
{
if (socket_handle[0] > socket_handle[1])
{
return socket_handle[0];
}
return socket_handle[1];
}
该代码应该绑定到端口9000和9001.它们使用select来查看哪些套接字有传入数据,然后打印该消息。
我假设它与我的recvfrom函数有关。我试过用参数玩弄没有用处。
另一个问题可能是当我设置套接字时,我正在使用sin6.addr = in6addr_any。我很确定PF_INET6和AF_INET6是正确的,但这也可能是一个问题。我一直在玩这个,但是我找不到这个bug。如果有人能指出我的错误,我会很感激,所以我可以修复它。我知道我正在完成这项工作。
这是一个家庭作业的问题,老师给我们的测试程序和它的作用仅仅是在端口发送一个消息9000
当调用recvfrom()
,您在client_length
设置,在输入了错误的值。它需要设置为sizeof(client_address[I])
。每次拨打电话recvfrom()
时,还需要重置client_length
。
打印收到的buffer
时,由于缓冲区不会以空值终止(除非客户端正在发送以空值终止的数据),因此您需要考虑bytes_received
。
试试这个:
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
int max_servers = 2;
int server_handle[max_servers];
int max_server_handle = 0;
struct sockaddr_in6 server_address[max_servers];
struct sockaddr_in6 client_address[max_servers];
char buffer[1000];
socklen_t client_length;
fd_set read_handles;
struct timeval timeout_interval;
int bytes_received;
int port_number = 9000;
int retval;
int i;
printf("Hello, human.\n");
for (i = 0; i < max_servers; i++)
{
printf("Creating socket %d on port: %d\n", i, port_number + i);
server_handle[i] = socket(PF_INET6, SOCK_DGRAM, 0);
if (server_handle[i] < 0)
{
perror("Unable to create socket.");
return -1;
}
if (server_handle[i] > max_server_handle)
max_server_handle = server_handle[i];
memset(&server_address[i], 0, sizeof(server_address[i]));
server_address[i].sin6_family = AF_INET6;
server_address[i].sin6_addr = in6addr_any;
server_address[i].sin6_port = htons(port_number + i);
if (bind(server_handle[i], (struct sockaddr *)&server_address[i], sizeof(server_address[i])) < 0)
{
perror("Unable to bind.");
return -1;
}
printf("Bind %d successful.\n", i);
}
while (1)
{
FD_ZERO(&read_handles);
for (i = 0; i < max_servers; i++)
FD_SET(server_handle[i], &read_handles);
timeout_interval.tv_sec = 2;
timeout_interval.tv_usec = 500000;
retval = select(max_server_handle + 1, &read_handles, NULL, NULL, &timeout_interval);
if (retval == -1)
{
printf("Select error\n");
//error
}
else if (retval == 0)
{
printf("timeout\n");
}
else
{
//good
for (i = 0; i < max_servers; i++)
{
if (FD_ISSET(server_handle[i], &read_handles))
{
client_length = sizeof(client_address[i]);
if ((bytes_received = recvfrom(server_handle[i], buffer, sizeof(buffer), 0, (struct sockaddr *)&client_address[i], &client_length)) < 0)
{
perror("Error in recvfrom.");
break;
}
printf("\nData received on socket %d:", i);
printf("\n--------------\n");
printf("%.*s", bytes_received, buffer);
}
}
}
}
}
我的错误。我有ipv6版本。 – 2013-03-07 00:44:23
除了底部的printf语句之外,当我认为完成了这一点之前,这就是我所做的,在所有的摆弄之前。它不会给我任何错误。这是输出: 数据接收:\ n -------------- \ n 已发送到端口9000 \ n 数据接收:\ n ------ -------- \ n “发送到端口9000”是从客户端发送的消息。它也应该说“发送到端口9001”。所以,recv函数都是成功的,但是我没有得到消息的字符串。 Wireshark显示这两个数据包都是有效的。编辑:我希望我可以在这里把换行符.. – 2013-03-07 01:49:47
我已经通过它。它不工作。我从你的代码镜像的唯一东西是这一行“printf(”%。* s“,bytes_received,buffer);”谢谢您的帮助! :] – 2013-03-07 05:40:22
请在这里展示你的代码 - pastebin.com超载,不会让我看看。 – Barmar 2013-03-07 00:35:21
Pastebin现在正在关闭。请删除您的代码,以证明您的问题,然后编辑您的问题以显示实际代码。 – 2013-03-07 00:35:28
@Barmer代码复制/粘贴在这里 – 2013-03-07 00:44:41