gpt4 book ai didi

c - Linux C 套接字 UDP 服务器。 select() 没有收到任何信息

转载 作者:太空宇宙 更新时间:2023-11-04 11:00:25 25 4
gpt4 key购买 nike

自从我输入了选择语句后,我的 UDP 服务器在接受任何输入时遇到了问题。目的是等待来自 2 个不同套接字(具有不同端口)的数据包。同时,我还希望它能够判断服务器何时要向正在同步监听的端口之一发送内容。在下面的代码中,程序一直运行到 select() 语句为止,此时如果我尝试向服务器(在本地机器上)发送一些东西,什么都不会被接受并且程序挂起,等待。我还尝试注释掉 writefds fd_set 及其随附的 FD_ISSET 但同样的事情发生了。我已经筋疲力尽地试图弄清楚这些东西,所以可能有很多东西没有意义,但我在目前的状态下尽力了。我很抱歉。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#define MYPORT "20444" // the port users will be connecting to
#define MAXBUFLEN 1024 //maximum packet length
#define SERVER_R 142.66.140.13 //Server to the "right" of current
#define RTEX_R_PORT "20445" //Port for routing table exchange

typedef enum {false, true} bool;

/*struct to store packet fields into
seq: sequence number;
type: message type; send get ACK
src: client's unique 10 digit number
dst: destination's unique 10 digit number
payload: the message being transferred, if there is any
*/
struct packet
{
char seq[4];
char type[5];
char src[11];
char dst[11];
char payload[MAXBUFLEN];
};

// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}

return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

int main(void)
{
//rr: reading from server to the "right"
//rw: writing to the server to the "right"
int sockfd, rtex_rr_sockfd, rtex_rw_sockfd, rv, rrr, rrw, numbytes, i, j, first, max_fd;
struct addrinfo hints, *servinfo, *p, *p2, *p3;
struct sockaddr_storage their_addr, right_addr;
fd_set readfds, writefds;
char buf[MAXBUFLEN];
char temp_buf[MAXBUFLEN];
char d_to_s[MAXBUFLEN];
char *field;
socklen_t addr_len;
char s[INET6_ADDRSTRLEN];
FILE *m_storage;
struct packet inet_packet;
static const struct packet EmptyPacket;
static int rt[51][4];
bool re_exists=false;
bool rt_empty=true;
struct timeval tv;

memset(&hints, 0, sizeof hints);//"zero out" the hints struct
hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE; // use my IP

//prepare socket address structures and store them in servinfo and store in linked list
if ((rv = getaddrinfo(NULL, MYPORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}

// loop through all the results and bind to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("listener: socket");
continue;
}

if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("listener: bind");
continue;
}

break;
}

if (p == NULL) {
fprintf(stderr, "listener: failed to bind socket\n");
return 2;
}

if ((rrr = getaddrinfo(NULL, RTEX_R_PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rrr));
return 1;
}

for(p2 = servinfo; p2 != NULL; p2 = p2->ai_next) {
if ((rtex_rr_sockfd = socket(p2->ai_family, p2->ai_socktype,
p2->ai_protocol)) == -1) {
perror("listener: socket");
continue;
}

if (bind(rtex_rr_sockfd, p2->ai_addr, p2->ai_addrlen) == -1) {
close(rtex_rr_sockfd);
perror("listener: bind");
continue;
}
break;
}

if (p2 == NULL) {
fprintf(stderr, "listener: failed to bind socket\n");
return 2;
}

if((rrw = getaddrinfo(NULL, RTEX_R_PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rrw));
return 1;
}

for(p3 = servinfo; p3 != NULL; p3 = p3->ai_next) {
if((rtex_rw_sockfd = socket(p3->ai_family, p3->ai_socktype,
p3->ai_protocol)) == -1) {
perror("server: socket");
continue;
}
break;
}

if (p3 == NULL) {
fprintf(stderr, "listener: failed to bind socket\n");
return 2;
}

//free up memory no longer needed after binding has completed
freeaddrinfo(servinfo);

FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_SET(rv, &readfds);
FD_SET(rrr, &readfds);
FD_SET(rrw, &writefds);

printf("Listen Mode\n");

//main while loop, listens for packets.
//Upon receipt of packet, information is stored in a struct for processing.
first=0;
while(1)
{
i=0;
inet_packet = EmptyPacket;
rt_empty=true;
tv.tv_sec = 50;
if(rv > rrr && rv > rrw)
max_fd = (rv + 1);
else if(rrr > rv && rrr > rrw)
max_fd = (rrr + 1);
else if(rrw > rv && rrw > rrr)
max_fd = (rrw + 1);

printf("before select...\n");
select(max_fd, &readfds, &writefds, NULL, NULL);
printf("after select...\n");
addr_len = sizeof their_addr;

if(FD_ISSET(rv, &readfds))
{
printf("rv is set...\n");
if((numbytes = recvfrom(sockfd, buf, sizeof(buf), 0,
(struct sockaddr *)&their_addr, &addr_len)) == -1) {
perror("recvfrom");
exit(1);
}
} else if(FD_ISSET(rrr, &readfds))
{
printf("rr read is set...\n");
if((numbytes = recvfrom(rtex_rr_sockfd, buf, sizeof(buf), 0,
(struct sockaddr *)&right_addr, &addr_len)) == -1) {
perror("recvfrom");
exit(1);
}
} else if(FD_ISSET(rrw, &writefds))
{
printf("rr write is set...\n");
if((numbytes = sendto(rtex_rw_sockfd, inet_packet.payload, sizeof(inet_packet.payload),
0, p3->ai_addr, p3->ai_addrlen)) == -1) {
perror("sendto rr");
exit(1);
}
}

最佳答案

运行你的程序,启动后在终端按回车键。它可能会从选择中返回。为什么?因为你告诉 select 唯一要听的是 fd 0,stdin! rvrrrrrw 都是 getaddrinfo() 的返回值,你只是忽略了实际的值fd 由 socket() 返回。 max_fd 也将是一个垃圾值,因为所有测试值都彼此相等。 (如果它恰好为零,它甚至不会对 stdin 使用react)

此外,下次请将代码缩减为 minimal example .如果您的问题是选择不返回,那么例如。所有的处理代码都是完全不相关的,一个套接字就足够了,使用 getaddrinfo() 是额外的。此外,您可能会在为了最小示例而删除 getaddrinfo() 内容时自己发现错误。

关于c - Linux C 套接字 UDP 服务器。 select() 没有收到任何信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27200445/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com