【问题标题】:C - UDP Client not completing SendTo to Echo ServerC - UDP 客户端未完成发送到 Echo 服务器
【发布时间】:2018-07-28 13:40:45
【问题描述】:

我正在尝试完成一个简单的回显服务器。目标是将消息重复回客户端。服务器和客户端都编译。服务器运行,你只需要给它一个运行的端口。客户端有地址、端口和消息。当客户端通过程序到达 sendto 部分时,它会停止并在那里等待。我的目标是将其发送到服务器,然后服务器将其发回。

我相信服务器可以正常工作,或者它至少处于接收模式,因为它进入了 while 循环来执行此操作。那部分可以发回它可以工作的注释。

对于客户端,我尝试直接发送参数,但也通过 c 字符串。我已经尝试了一个硬编码,但都没有工作。我已经玩了好几个小时了,所以我决定寻求帮助,因为作为新手,我想不出其他任何东西。

客户

//argv[1] address, argv[2] port, argv[3] message
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>

int main(int argc, char *argv[]){

int BUF_LEN;

for (BUF_LEN = 0; argv[3][BUF_LEN] != '\0'; BUF_LEN++){
//  printf("BUF_LEN = %i\n", BUF_LEN);
}
    int s, n, port_no, r;
    struct sockaddr_in server_addr;
    char *haddr, *message;
    char buf[BUF_LEN+1];

printf("Variables created\n");

    s = socket(AF_INET, SOCK_DGRAM, 0); // create a socket for UDP

printf("Socket created as s: %i\n", s);

bzero((char *)&server_addr, sizeof(server_addr));   // clear

server_addr.sin_family = AF_INET;   //IPv4 Internet family
server_addr.sin_addr.s_addr = inet_addr(argv[1]);   //server address
server_addr.sin_port = htons(atoi(argv[2]));    // server port number

printf("Server addr complete\n");

//Bind() - Not necessary

printf("Bind skipped\n");

//sendto()
    r = sendto(s, argv[3], strlen(argv[3]), 0, (struct sockaddr *)&server_addr, BUF_LEN);
    printf("Message Sent");

//recvfrom()
    n = recvfrom (s, buf, BUF_LEN, 0, (struct sockaddr *)&server_addr, &BUF_LEN);
    printf("Message Received: %s\n", buf);

close(s);

}

服务器

//Argv[1] : port number
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>

int main(int argc, char *argv[]){

int n; 
int MAXLINE = 512;
int sock_server, sock_client, r, len;
char buf[MAXLINE];
struct sockaddr_in my_addr, client_addr;    

//printf("Variables created\n");

sock_server = socket (PF_INET, SOCK_DGRAM, 0); 

//printf("Socket created\n");

if (sock_server < 0){
    perror("Bind failed");
    exit(1);
}

bzero(&my_addr, sizeof(my_addr));       // clear

my_addr.sin_family = AF_INET;           //Address Family INET
my_addr.sin_port = htons(atoi(argv[1]));    //Server port number
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);    // Accept from anywhere

//printf("Addresses created\n");

r = bind(sock_server, (struct sockaddr*)(&my_addr), sizeof(my_addr));
    if (r < 0) {
        perror("Bind failed");
        exit(1);
    }

printf("Read to receive\n");

while(1) {

//printf("First while loop\n");

len = sizeof(struct sockaddr_in);

    //recvfrom()
    n = recvfrom (sock_client, buf, MAXLINE, 0, (struct sockaddr *)&client_addr, &len);

while (n > 1){
    printf("Second while loop\n");

    printf("Message Received: %s\n", buf);

    //sendto()
    sendto(sock_client, buf, n, 0, (struct sockaddr *)&client_addr, len);
    n = 0;
    }
}

    close(sock_client);     //close the client socket
//printf("Connection sock_client Closed");
}

【问题讨论】:

  • 在客户端,sendto 不应该使用BUF_LEN。看起来你在服务器上做对了,虽然我会在 sendto 调用之前重新初始化 len 变量。
  • 只是为了澄清@user3386109 发布...在您的客户中,您调用“sendto”的最后一个参数(第 6 个)不正确...最后一个参数应该是“sizeof”的下一个-最后一个(第5个)参数......在你的情况下是“sizeof(server_addr)”。如果您检查了“sendto”的返回码,您可能已经发现了它......此外,您使用命令行参数而不检查“argc”以确保使用适当数量的参数调用您的客户端。
  • 如何找到sendto的返回码?我试图用 var = sendto 命令将它连接到一个变量,但是在尝试完成它时它仍然挂起。我已经更改了行,以便最后两个变量说 &server_addr, sizeof(server_addr));但它仍然挂在那里,没有继续到它之后的 printf 行。
  • 除了@TonyB 解释的内容之外,我想您错误地认为sendto 挂起,因为您没有看到"Message Sent" 打印。 stdout 是行缓冲的,在出现 \n 字符之前不会打印任何内容。客户肯定挂在recvfrom
  • 谢谢你,我认为你是对的。在我将 \n 添加到“发送的消息”之后,就会出现该 printf 消息。现在它等待来自 recvfrom 的响应。从更多的研究来看,它需要一个 \n 来推动它通过缓冲区,或者一个 fflush(stdout) 命令。我只是在这里记录一下,以防其他人出现在这篇文章中,这样他们就不需要问同样的问题了。现在我将在 recvfrom 位上进行更多工作,看看是否能找到解决方案。

标签: c server udp echo


【解决方案1】:

这是在sendto的客户端调用中使用sizeof(server_addr)的客户端的固定版本:

//argv[1] address, argv[2] port, argv[3] message
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>

int main(int argc, char *argv[]){

  int BUF_LEN;

  for (BUF_LEN = 0; argv[3][BUF_LEN] != '\0'; BUF_LEN++){
    //  printf("BUF_LEN = %i\n", BUF_LEN);
  }

  int s, n, port_no, r;
  struct sockaddr_in server_addr;
  char *haddr, *message;
  char buf[BUF_LEN+1];

  printf("Variables created\n");

  s = socket(AF_INET, SOCK_DGRAM, 0); // create a socket for UDP

  printf("Socket created as s: %i\n", s);

  bzero((char *)&server_addr, sizeof(server_addr));   // clear

  server_addr.sin_family = AF_INET;   //IPv4 Internet family
  server_addr.sin_addr.s_addr = inet_addr(argv[1]);   //server address
  server_addr.sin_port = htons(atoi(argv[2]));    // server port number

  printf("Server addr complete\n");

  //Bind() - Not necessary

  printf("Bind skipped\n");

  r = sendto(s, argv[3], strlen(argv[3]), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
  printf("Message Sent");

  n = recvfrom (s, buf, BUF_LEN, 0, (struct sockaddr *)&server_addr, &BUF_LEN);
  printf("Message Received: %s\n", buf);

  close(s);

}

【讨论】:

  • 感谢您发布此信息。我尝试使用它,它仍然挂在 sendto 位置。
  • 我想通了。在服务器中,它必须是这样的... sendto(sock_server, buf, n, 0, (struct sockaddr *)&client_addr, len); sock_client 没关系。您是发布答案的人,这对第一部分有所帮助,所以我向您致敬,先生。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多