C/select仅从一个文件描述符读取
新的一天,新的问题。顺便说一句,我发现自己几乎每天都在这里问问题。谢谢你迄今为止的支持。我实现了select从四个文件描述符读取,但它只从一个文件描述符读取 我有一个测试应用程序将所有四个端口上的数据包发送到第二台机器,其中C程序正在运行:C/select仅从一个文件描述符读取,c,sockets,C,Sockets,新的一天,新的问题。顺便说一句,我发现自己几乎每天都在这里问问题。谢谢你迄今为止的支持。我实现了select从四个文件描述符读取,但它只从一个文件描述符读取 我有一个测试应用程序将所有四个端口上的数据包发送到第二台机器,其中C程序正在运行: data_packet to port[13501] data_packet to port[13502] data_packet to port[13503] data_packet to port[13504] data_packet to port[1
data_packet to port[13501]
data_packet to port[13502]
data_packet to port[13503]
data_packet to port[13504]
data_packet to port[13501]
等等
使用tcpdump,我可以看到测试应用程序工作正常:
08:02:26.391843 IP 10.1.1.2.2000 > 10.1.1.40.13501: UDP, length: 28
08:02:27.391794 IP 10.1.1.2.2000 > 10.1.1.40.13502: UDP, length: 28
08:02:28.391820 IP 10.1.1.2.2000 > 10.1.1.40.13503: UDP, length: 28
08:02:29.391918 IP 10.1.1.2.2000 > 10.1.1.40.13504: UDP, length: 28
但我的应用程序只是从一个FD套接字读取,开始时我显示FD_集中所有可用的文件描述符:
围绕select的实现如下所示:
FD_SET(sock_fd[i], &read_fds);
fdmax = sock_fd[i];
}
for(i = 0; i < 4; i++) {
printf("sock_fd[%d]\n",sock_fd[i]);
}
while(keepRunning) {
bzero(&incoming_msg, MAX_PAYLOAD_LEN);
bzero(&outgoing_msg, MAX_PAYLOAD_LEN);
bzero(&peer, peer_len);
readsocks = select(fdmax+1, &read_fds, NULL, NULL, NULL);
if (readsocks < 0) {
perror("select");
exit(EXIT_FAILURE);
} else if (readsocks == 0) {
printf("nothing to read from\n");
continue;
}
for(i = 0; i < 4; i++) {
if(FD_ISSET(sock_fd[i], &read_fds)) {
in_msg_len = recvfrom(sock_fd[i],
incoming_msg,
MAX_PAYLOAD_LEN,
0,
(struct sockaddr *) &client_addr,
&sock_len_client);
if (in_msg_len < 0) {
perror("failed to receive data\n");
exit(EXIT_FAILURE);
}
strncpy(outgoing_msg, incoming_msg, in_msg_len);
if(getsockname(sock_fd[i], &peer, &peer_len) < 0) {
perror("getsockname() failed");
return (-1);
}
receiving_eth_port = (int)ntohs(peer.sin_port);
#if DBG_OUTPUT
printf("received on sock_fd[%d] on ETH0 on port %d\n", sock_fd[i], receiving_eth_port);
#endif
如何实现从所有套接字选择读取…?选择更改您的读取
在第一次调用select之后,read_fds可能只设置了一个fd位,因此您只在所有剩余循环中检查该文件描述符
解决方案是在每次调用select之前重新构建read_fds。这听起来可能很乏味,但这是处理select时的常见做法。1我在循环中的任何地方都没有看到FD_设置。2 strncpy是伪的,相当于memcpyth。我添加了FD_集,它在select循环开始之前在另一个循环中完成。什么是“伪造”->translate.google.de->为什么错了?把它们放在循环中。假的意思是胡说八道。strncpy没有错,只是没有意义。recv的返回值是字符数。strncpy最多复制cnt字符,cnt是第三个参数。如果在cnt字符之前的第二个参数中未遇到NUL字节,则仅复制cnt字符。不添加尾随的NUL字节。此外,如果遇到NUL字节,将复制少于cnt字节。多亏了您和这里的示例,我可以解决这个问题。非常好的评论,谢谢!
FD_SET(sock_fd[i], &read_fds);
fdmax = sock_fd[i];
}
for(i = 0; i < 4; i++) {
printf("sock_fd[%d]\n",sock_fd[i]);
}
while(keepRunning) {
bzero(&incoming_msg, MAX_PAYLOAD_LEN);
bzero(&outgoing_msg, MAX_PAYLOAD_LEN);
bzero(&peer, peer_len);
readsocks = select(fdmax+1, &read_fds, NULL, NULL, NULL);
if (readsocks < 0) {
perror("select");
exit(EXIT_FAILURE);
} else if (readsocks == 0) {
printf("nothing to read from\n");
continue;
}
for(i = 0; i < 4; i++) {
if(FD_ISSET(sock_fd[i], &read_fds)) {
in_msg_len = recvfrom(sock_fd[i],
incoming_msg,
MAX_PAYLOAD_LEN,
0,
(struct sockaddr *) &client_addr,
&sock_len_client);
if (in_msg_len < 0) {
perror("failed to receive data\n");
exit(EXIT_FAILURE);
}
strncpy(outgoing_msg, incoming_msg, in_msg_len);
if(getsockname(sock_fd[i], &peer, &peer_len) < 0) {
perror("getsockname() failed");
return (-1);
}
receiving_eth_port = (int)ntohs(peer.sin_port);
#if DBG_OUTPUT
printf("received on sock_fd[%d] on ETH0 on port %d\n", sock_fd[i], receiving_eth_port);
#endif