我想从不同的客户端接收数据(客户端数量是固定的,比如10),并且每个客户端在5个不同的预定义端口上发送数据,这些端口不会更改。(例如,客户端1端口5000,5001,5002,等。)所有客户端可以同时发送数据。 (以上都是固定的)
在TCP中说,我可以为我们接受的每个连接创建多个线程,如下所示。 UDP是无连接的,那么我们如何为每个UDP客户端(UDP端口)创建一个线程来处理并发数据?就像每个线程都有一个receivefrom()函数来获取数据一样。
// UDP服务器
#define BUFLEN 512
#define CLIENT1_PORT1 5000
#define CLIENT1_PORT2 5001
#define CLIENT1_PORT3 5002
#define CLIENT2_PORT1 5050
#define CLIENT2_PORT2 5051
#define CLIENT2_PORT3 5052
#define CLIENT3_PORT1 6000
#define CLIENT3_PORT2 6001
#define CLIENT3_PORT3 6002
void diep(char *s) {
perror(s);
exit(1);
}
int main(void) {
struct sockaddr_in client1_sockaddr_1, client1_sockaddr_2,client2_sockaddr_1,client2_sockaddr_2, si_other;
int c1_sockfd_1,c1_sockfd_2, c2_sockfd_1,c2_sockfd_2, i, slen = sizeof(si_other);
char buf[BUFLEN];
/******for client 1 port1 **********/
if((c1_sockfd_1 = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
diep("socket");
memset((char *) &client1_sockaddr_1, 0, sizeof(client1_sockaddr_1));
client1_sockaddr_1.sin_family = AF_INET;
client1_sockaddr_1.sin_port = htons(CLIENT1_PORT1);
client1_sockaddr_1.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(c1_sockfd_1, (struct sockaddr *) &client1_sockaddr_1, sizeof(client1_sockaddr_1)) == -1)
diep("bind");
if((c2_sockfd_1 = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
diep("socket");
/*******for client 2 port1 *******/
memset((char *) &client2_sockaddr_1, 0, sizeof(client2_sockaddr_1));
client2_sockaddr_1.sin_family = AF_INET;
client2_sockaddr_1.sin_port = htons(CLIENT2_PORT1);
client2_sockaddr_1.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(c1_sockfd_2, (struct sockaddr *) &client2_sockaddr_1, sizeof(client2_sockaddr_1)) == -1)
diep("bind");
//Receive from clients
while(1) {
/*How to create threads at this point and have a separate recvfrom for each client port ??*/
if(recvfrom(c1_sockfd_1, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == -1)
diep("recvfrom()");
printf("Recieved packet from %s: %d\nData: %s\n\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port), buf);
}
close(c1_sockfd_1);
return 0;
}
更新 我喜欢每个客户端5个端口,总共5 * 10个插槽,数据将在几毫秒的时间间隔内同时发送。每个端口收到的数据包大小不同。数据包与Header和CRC一起发送。为了跟踪和重新请求丢失的数据包,有一个包号是一个好主意吗?
(或)使用UDP跟踪丢失数据包和请求它们的不同方法有哪些?
答案 0 :(得分:3)
线程的替代方法是select()函数,它提供同步I / O复用。您可以向select()函数提供5个套接字fds,并等待其中一个fds准备好数据。冲洗并重复。
查看手册页:http://linux.die.net/man/2/select或网上的许多教程。
答案 1 :(得分:1)
您不需要多个线程。
如果您的瓶颈是IO,则线程无法提供帮助。
如果您的瓶颈是处理/ CPU,请在一个线程中接受它们,然后分派到多个线程。
答案 2 :(得分:1)
如果你想要一个线程每端口解决方案:对于每个端口号p创建一个线程并将其作为参数传递给那么线程将执行:socket(); bind(p),while(1){recvfrom();发送至(); }