【问题标题】:UDP sockets - server not receiving any dataUDP 套接字 - 服务器没有接收到任何数据
【发布时间】:2016-06-20 11:07:12
【问题描述】:

我正在尝试开发一个 UDP 客户端-服务器程序。这是我的代码:

服务器

int main(int argc, char *argv[]) {
    struct sockaddr_in client, server;
    int s, i=0;
    socklen_t n;
    char buf[4];
    s=socket(AF_INET,SOCK_DGRAM,0);
    server.sin_family=AF_INET;
    server.sin_port=atoi(argv[1]);
    inet_pton(AF_INET, "localhost", &(server.sin_addr));
    bind(s,(struct sockaddr *)&server,sizeof(server));
    n=sizeof(client);

    while(1) {
        recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&client, &n);
        printf("%s", buf);
    }
    close(s);
    return 0;
}

客户

int main (int argc, char *argv[]) {
    struct sockaddr_in client, server;
    int s, n;
    char buf[30];
    char temp[4];
    s=socket(AF_INET,SOCK_DGRAM,0);
    server.sin_family=AF_INET;
    server.sin_port=atoi(argv[2]);
    inet_pton(AF_INET, argv[1], &(server.sin_addr));

    n=sizeof(server);

    while(1) {
        scanf("%s", buf);
        fflush(stdin);
        sendto(s, buf, sizeof(buf), 0, (struct sockaddr *) &server, n);
    }
    close(s);
    return 0;
}

本质上相当基本,没有任何错误处理。服务器输出客户端发送的任何内容。

在我测试某些东西时忘记删除/释放动态分配的内存后,它停止在我的 Ubuntu 机器上工作。它在不同的 Linux 服务器上运行良好。

知道是什么原因造成的吗?未关闭的端口,内存泄漏?我该如何解决这个问题?

【问题讨论】:

  • fflush(stdin); 调用未定义的行为,所以不要使用它。
  • printf("%s", buf); 也可以调用 undefined behavior 如果 buf 中的内容不是以空值结尾的字符串。打印前正确终止“字符串”,或以其他方式打印。
  • 以前,我的程序卡在无法读取数据,所以我不得不强制清理标准输入缓冲区。还有更好的选择吗?
  • 我正在尝试发送:temp[0] = 't'; temp[1] = 'e'; temp[2] = 'm'; temp[3] = '\0'; 仍然无法正常工作。
  • “没有任何错误处理”。在完成这些基础知识之前,您真的不应该在这里发帖。这不是对社区时间的有效利用。如果您添加错误检查,它可能会帮助您自己解决问题,或者至少让您或我们更接近问题所在。

标签: c linux sockets ubuntu udp


【解决方案1】:

首先,正如@kaylum 提到的,您需要检查错误。除此之外,我还发现了几个问题:

  • inet_pton() 不会将主机名转换为地址。通常,你 不想绑定到服务器端的特定 IP 地址 反正;相反,将其设置为INADDR_ANY。在客户端,127.0.0.1 将用于发送到同一台机器上的服务器。
  • 您需要将端口号转换为网络字节顺序 htons()
  • 您正在发送 30 个字节,但您的接收缓冲区只有 4 个字节长。 有人提到你不应该发送整个 30 字节 缓冲区,但这取决于您和您的协议。你只需要成为 能够处理正在发送的任何内容。
  • 正如其他人所提到的,fflush(stdin) 不正确;使用fflush() 用于刷新输出,但stdin 是输入文件。
  • scanf("%s", buf) 不限制输入到缓冲区的大小, 所以这可能会导致问题。请改用fgets()

【讨论】:

    【解决方案2】:

    您的方法存在问题:

    • fflush(stdin); 调用未定义的行为。如果您想读取并丢弃用户输入的其余行,请使用:

      scanf("%*[^\n]");  /* consume all remaining chars on the line, if any */
      scanf("%*c");      /* consume the linefeed if any */
      
    • 客户端代码应该只发送字符串,可能带有分隔符,但不是整个缓冲区,其中部分未初始化:

      sendto(s, buf, strlen(buf), 0, (struct sockaddr *)&server, n);
      
    • 服务器代码应该为空终止从客户端接收到的缓冲区:

      while(1) {
          ssize_t nr = recvfrom(s, buf, sizeof(buf) - 1, 0, (struct sockaddr *)&client, &n);
      
          if (nr >= 0) {
              buf[nr] = '\0';
              printf("%s", buf);
          }
      }
      
    • 客户端和服务器都应该优雅地处理文件结束和系统调用失败。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-07
      • 1970-01-01
      • 2021-10-02
      • 1970-01-01
      • 1970-01-01
      • 2015-11-28
      相关资源
      最近更新 更多