逗人,
如果你能引导我解决这个问题,我将不胜感激。
首先,让我介绍一下这个场景。
情景是: - 一台具有两个网络接口的设备作为发送方。 - 一个带有两个网络接口的设备作为接收器。
我们正在尝试模拟能够从移动网络(例如4G)和wifi网络接收数据包的移动设备。
必须使用UDP套接字完成通信。
发件人通过两个接口(不是并行)随机发送数据包。 接收方必须准备好接收来自每个接口的数据包
接收器和发送器都有两个UDP套接字。每个UDP套接字都分配给不同的环回接口(127.0.0.1和127.0.0.2),并具有相同的端口号(不同的IP,相同的端口号)。
sockaddr_in结构是serverAddr:
serverAddr[i].sin_family = AF_INET;
serverAddr[i].sin_addr.s_addr = htonl(INADDR_ANY);
serverAddr[i].sin_port = htons(PORTNUM);
setsockopt(socketFileDescriptor[i], SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(int));
接收器在recvfrom方法中阻塞了两个线程。程序启动时,两个线程都在等待数据包。无论哪个客户端接口发送第一个数据包,从第二个数据包开始,每个新数据包似乎都被127.0.0.1接口接收。我知道INADDR_ANY允许接收发往任何接口的数据包。
我的怀疑是:为什么不再在127.0.0.2接口接收数据包了?监听来自不同网络接口的数据包的正确方法是什么?
服务器端代码:
struct info {
int socketDescriptor;
struct sockaddr_in addr;
unsigned int size;
};
int udpEchoServer();
void *connection_handler(void *socketInfo);
int main(int argc, char** argv)
{
udpEchoServer();
puts("Press any key to continue");
getc(stdin);
return EXIT_SUCCESS;
}
int udpEchoServer()
{
int socketFileDescriptor[NUM_CONNECTIONS], enable = 1, client_sock;
struct sockaddr_in serverAddr[NUM_CONNECTIONS];
//struct sockaddr_in clientAddr;
info socketInfo[NUM_CONNECTIONS];
pthread_t thread[NUM_CONNECTIONS];
const char* interfaces[] = {"127.0.0.1", "127.0.0.2"};
for (int i = 0; i < NUM_CONNECTIONS; i++){
socketFileDescriptor[i] = socket(AF_INET, SOCK_DGRAM, 0);
if(socketFileDescriptor[i] == -1) {
perror("Error on socket creation\n");
return EXIT_FAILURE;
}
if (setsockopt(socketFileDescriptor[i], SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0)
printf("setsockopt(SO_REUSEADDR) failed");
bzero(&serverAddr[i], sizeof(serverAddr[i]));
serverAddr[i].sin_family = AF_INET;
serverAddr[i].sin_addr.s_addr = htonl(INADDR_ANY);
serverAddr[i].sin_port = htons(PORTNUM);
if (bind(socketFileDescriptor[i], (struct sockaddr*)& serverAddr, sizeof(serverAddr)) == -1) {
close(socketFileDescriptor[i]);
perror("bind failed socket\n");
return EXIT_FAILURE;
}
printf("Socket #%d listening\n", socketFileDescriptor[i]);
socketInfo[i].socketDescriptor = socketFileDescriptor[i];
socketInfo[i].addr = serverAddr[i];
socketInfo[i].size = sizeof(serverAddr[i]);
}
printf("Waiting incomming!!\n");
int nThreads = 0;
while (nThreads < NUM_CONNECTIONS)
{
printf("++++++ Creating reception thread %d\n", nThreads);
if( pthread_create( &thread[nThreads] , NULL , connection_handler , (void*) &socketInfo[nThreads]) < 0)
{
perror("could not create thread");
return EXIT_FAILURE;
}
sleep(1);
/
printf("nThreads = %d\n", nThreads++);
}
for (int i = 0; i < NUM_CONNECTIONS; i++) {
pthread_join(thread[i], NULL);
}
return EXIT_SUCCESS;
}
void *connection_handler(void *socketInfo)
{
//Get the socket descriptor
info *newSocketInfo = (info*)socketInfo;
int n;//, local_sock;
char clientname[200];
pthread_t self_id;
self_id=pthread_self();
while (true) {
printf("=========> Waiting connection in thread #%u\n", self_id);
printf("newSocketInfo->socketDescriptor = %d\n", newSocketInfo->socketDescriptor);
printf("Adress = %s\n",inet_ntop(AF_INET,&newSocketInfo->addr.sin_addr, clientname, sizeof(clientname)));
char client_message[2000];
printf("Waiting packets\n");
n = recvfrom(newSocketInfo->socketDescriptor, client_message, sizeof(client_message), 0, (struct sockaddr *)&newSocketInfo->addr, &newSocketInfo->size);
sleep(1);
printf("++ %d Bytes received at %d. Sending it back\n", n, newSocketInfo->socketDescriptor);
sendto(newSocketInfo->socketDescriptor,client_message,n,0, (struct sockaddr *)&newSocketInfo->addr, newSocketInfo->size);
if(n==0) {
puts("Client Disconnected");
} else if (n > 0) {
puts("recvfrom ok");
} else {
perror("read failed");
}
sleep(1);
}
return 0;
}
提前致谢