【问题标题】:UDP Socket - Server hanging on recvfromUDP Socket - 服务器挂在 recvfrom
【发布时间】:2015-06-11 05:56:58
【问题描述】:

我正在尝试实现客户端-服务器网络。我关注Beej's Guide to Network Programming

我的程序扫描来自键盘的输入,在数组中查找相关值,然后通过UDPGET request 发送到我的服务器。但是,我的服务器似乎没有收到我的请求。

这是我的客户端代码摘录:

    // loop through all the results and make a socket
for(p = servinfo; p != NULL; p = p->ai_next) {
    if ((sockfd = socket(p->ai_family, p->ai_socktype,
            p->ai_protocol)) == -1) {
        perror("talker: socket");
        continue;
    }

    break;
}

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

printf("Please Enter Your Search (USC, UCLA etc.):");
char searchKey[5];
fgets(searchKey, sizeof(searchKey), stdin);
int len, bytes_sent;
char value[8];
len = strlen(value);
char request[10];
for(int i = 0; i < sizeof(clientMap) / sizeof(struct Mapping); i++) {
  if (strcmp(clientMap[i].key, searchKey) == 0) {
    //value = clientMap[i].value;
    memcpy(value, clientMap[i].value, sizeof(char) * 6);
    strcat(request, "GET ");
    strcat(request, value);
    break;
  }
}
printf("The Client 1 has received a request with search word %s, which maps to key %s\n", searchKey, value);
printf("The Client 1 sends the request %s to the Server 1 with port number %s and IP address %s\n", request, SERVERPORT, argv[1]);
printf("The Client1's port number is TODO and the IP address is TODO\n");
if ((numbytes = sendto(sockfd, request, strlen(request), 0,
         p->ai_addr, p->ai_addrlen)) == -1) {
    perror("talker: sendto");
    exit(1);
}

freeaddrinfo(servinfo);

printf("talker: sent %d bytes to %s\n", numbytes, argv[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;
}

freeaddrinfo(servinfo);

printf("listener: waiting to recvfrom...\n");

addr_len = sizeof their_addr;
if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0,
    (struct sockaddr *)&their_addr, &addr_len)) == -1) {
    perror("recvfrom");
    exit(1);
}

buf[numbytes] = '\0';
printf("The Server 1 has received a request with key %s\n", buf);
for(int i = 0; i < sizeof(serverMap) / sizeof(struct Mapping); i++) {
  if (strcmp(serverMap[i].key, buf) == 0) {
    char post[13];
    strcpy(post, "POST ");
    strcat(post, serverMap[i].value);
    printf("The Server 1 sends the reply %s to TODO: Finish this!", post);
    sendto(sockfd, post, strlen(post), 0, (struct sockaddr *)&their_addr, addr_len);
    break;
  }
}
close(sockfd);

我知道问题是我的服务器没有收到数据报。我想我犯了一些明显容易的错误,但我对CNetworks 的理解不是那么强。

在旁注中,您可能会注意到我的打印语句包含TODOs。我不确定如何获取这些IP addressesport numbers。有人也可以帮忙吗?

【问题讨论】:

  • 1) len = strlen(value); 值未初始化 2) if (strcmp(clientMap[i].key, searchKey) == 0) { searchkey 末尾可能还有一个 '\n'(除非输入的字符串长度==4)
  • 服务器可能未绑定到端口。如果您不知道发送到哪个 ip 和哪个端口,您将如何发送?我不明白为什么你有那个循环,而 p 链表数据结构中的内容非常重要。
  • @PhilipStuyck 服务器绑定在我没有包含的代码中。对不起。此外,如果我正确理解了 Beej 的指南,则循环是尝试遍历所有返回的结果并尽可能绑定到第一个结果。 Beej 似乎强调有一些新旧的编码方式
  • 我不知道 Beej,但是一个迭代端口和/或 IP 地址列表的服务器很奇怪。

标签: c sockets network-programming udp recvfrom


【解决方案1】:

你的服务器无论如何都需要一个固定的端口来监听。您如何期望您的客户知道它应该发送到哪个端口? 只需在服务器和客户端上使用任意端口即可。

由于您是新手,请先在本地尝试一切。 服务器应该监听 INADDR_ANY 和您选择的任意端口。

【讨论】:

  • @Phillip 我用#define MYPORT "21474" 定义了客户端和服务器端的端口,但我想我明白你的意思了。看来我的服务器绑定但我的客户端没有。我现在通过将if (bind(sockfd, p-&gt;ai_addr, p-&gt;ai_addrlen) == -1) { close(sockfd); perror("listener: bind"); continue; } 复制到我的客户端代码中来尝试您的建议
  • 客户端不需要绑定。它使用 sendto 并且地址参数中的端口应该与您在服务器和服务器 ip@ 中定义的端口相同,但如果您在本地运行,那当然是 127.0.0.1,而不是点分符号。
  • 顺便说一句,不要忘记端口的 htons 和 IP 地址的 htonl。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-11
  • 2018-05-14
  • 1970-01-01
  • 1970-01-01
  • 2018-03-28
相关资源
最近更新 更多