Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets UDP说话者给出;ai“U标志”的值不正确;关于sendto()调用_Sockets_Udp_Sendto - Fatal编程技术网

Sockets UDP说话者给出;ai“U标志”的值不正确;关于sendto()调用

Sockets UDP说话者给出;ai“U标志”的值不正确;关于sendto()调用,sockets,udp,sendto,Sockets,Udp,Sendto,我被我的UDP talker应用程序卡住了。 目前的目标是初始化服务器,注册客户机,然后继续向该客户机发送一些内容。 我已经阅读了Beej的网络指南,并编写了以下库实现: 这将使服务器序列化 int init_udp_server(const char *port_string){ /** Check the input data **/ if(port_string == NULL) port_string = DEFAULT_PORT; /** Get the inf

我被我的UDP talker应用程序卡住了。 目前的目标是初始化服务器,注册客户机,然后继续向该客户机发送一些内容。 我已经阅读了Beej的网络指南,并编写了以下库实现:

这将使服务器序列化

int init_udp_server(const char *port_string){

  /** Check the input data **/
  if(port_string == NULL)
    port_string = DEFAULT_PORT;

  /** Get the information for the server **/
  memset(&addrinfo_hints, 0, sizeof addrinfo_hints);
  /* Use either protocol (v4, v6) */
  addrinfo_hints.ai_family = AF_UNSPEC;
  /* Use UDP socket type */
  addrinfo_hints.ai_socktype = SOCK_DGRAM;
  /* Use system IP */
  addrinfo_hints.ai_flags = AI_PASSIVE;

  if( (ret = getaddrinfo(NULL, port_string, &addrinfo_hints, &addrinfo_server)) 
      != 0 ){
    printf("Server:getaddrinfo: %s\n", gai_strerror(ret));  
    return -1;
  }

  /** Loop through the list returned by getaddrinfo and get socket **/
  for( addrinfo_queue = addrinfo_server; addrinfo_queue != NULL; 
      addrinfo_queue = addrinfo_queue->ai_next){
    if((sockfd = socket(addrinfo_queue->ai_family,
            addrinfo_queue->ai_socktype, addrinfo_queue->ai_protocol)) == -1){
      error("Server: get socket failed");
      continue;
    }
    if(bind(sockfd, addrinfo_queue->ai_addr, addrinfo_queue->ai_addrlen)
        == -1){
      close(sockfd);
      error("Server: Bind to socket error");
      continue;
    }
    break;

  }
  /* If we got to addrinfo_queue == NULL, we did not get a valid socket */
  if(addrinfo_queue == NULL){
    error("Server: Could not bind a socket");
    return -1;
  }
  /* We do not need the addrinfo_server anymore */
  freeaddrinfo(addrinfo_server);
  return 0;
}
这将注册客户端

int udp_server_setup_client(const char *client_addr, const char *port_string, int     client_nr){


  /** Check the input data **/
  if(port_string == NULL)
    port_string = DEFAULT_PORT;
  if(client_addr == NULL){
    error("No valid client list");
    return -1;
  }
  if(client_nr < 0 || client_nr > 7){
    error("No valid client Nr.");
    return -1;
  } 

  memset(&addrinfo_hints, 0, sizeof addrinfo_hints);
  /* Use either protocol (v4, v6) */
  addrinfo_hints.ai_family = AF_UNSPEC;
  /* Use UDP socket type */
  addrinfo_hints.ai_socktype = SOCK_DGRAM;

  /* Get the information for the client */
  if( (ret = getaddrinfo( client_addr, port_string, &addrinfo_hints,
          &current)) != 0 ){
    printf("Client:getaddrinfo: %s\n", gai_strerror(ret));  
    return -1;
  }
  else{
    /* We read out the IP, kind of a nice check to see wheter all went fine */
    char ip4[INET_ADDRSTRLEN];
    struct sockaddr_in *sa = (struct sockaddr_in*) current->ai_addr;
    inet_ntop(AF_INET, &(sa->sin_addr),ip4, INET_ADDRSTRLEN);
    printf("Clients address: %s\n",ip4);
    addrinfo_clients[client_nr] = current;
  }
  return 0;
}
调用sendto()后,我立即收到一个错误: 无法将消息发送到客户端0 错误代码:ai_标志的值不正确 我用gdb检查了它,发现addrinfo结构填写正确,并且客户端的地址有效。 有人知道去哪里找吗?我的想法快用完了

谢谢,wenzlern

调用
sendto()
时,最后一个参数被设置为
sizeof current->ai_addr
,这是错误的
current->ai_addr
被定义为
sockaddr*
指针,因此
sizeof current->ai_addr
在32位系统上总是返回4,在64位系统上总是返回8。恰好IPv4地址的大小为4个字节,因此
sizeof current->ai_addr
将仅适用于32位系统上的IPv4地址,但对于32位系统上的IPv6地址和64位系统上的所有地址,将始终失败。您需要使用
current->ai_addrlen
而不是
sizeof

此外,将-1传递给
gai_strerror()
无效。它希望您传入一个真正的错误代码,例如
getaddrinfo()
getnameinfo()
的返回值
sendto()
不返回实际的错误代码。当它失败时,您必须在Windows上使用
WSAGetLastError()
,或在其他系统上使用
errno
,以获取实际的错误代码

试试这个:

if ((ret = sendto(sockfd, (char*)buffer, buffer_size, 0, (sockaddr*)current->ai_addr, current->ai_addrlen)) == -1)
{
    #ifdef _WIN32
    ret = WSAGetLastError();
    #else
    ret = errno;
    #endif

    printf("Failed to send message to client %i\n", client_nr);
    printf("Error Code: (%d) %s\n", ret, gai_strerror(ret)); 
    return -1;    
}

从getaddrinfo的主页中:EAI_BADFLAGS hints.ai_flags包含无效标志;或者,hits.ai_标志包括ai_名称,且名称为空。我不知道其中一个怎么适用。非常感谢!你的纠正解决了问题。我在一台64位的机器上工作,所以它确实因为socklen构造而不断失败。再次感谢!你好,温兹伦
init_udp_server("3334"); 

udp_server_setup_client("192.168.1.5", "3334", 0);

udp_server_write(send_buf, 256, 0);
if ((ret = sendto(sockfd, (char*)buffer, buffer_size, 0, (sockaddr*)current->ai_addr, current->ai_addrlen)) == -1)
{
    #ifdef _WIN32
    ret = WSAGetLastError();
    #else
    ret = errno;
    #endif

    printf("Failed to send message to client %i\n", client_nr);
    printf("Error Code: (%d) %s\n", ret, gai_strerror(ret)); 
    return -1;    
}