-1

我正在尝试在 C 中创建一个客户端/服务器程序(两个程序位于不同的机器上而不是本地主机上),但使用的协议仅是 IPv6。当我运行客户端时,它会在 connect() 处暂停一段时间然后失败。为什么 connect() 失败?

服务器代码:

#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<unistd.h>
#include<netdb.h>
int main()
{
 int sockfd,connfd,rv;
 struct addrinfo hints,*servinfo,*p;
 struct sockaddr_in6 client_addr;

 memset(&hints,0,sizeof hints);

 hints.ai_family=AF_INET6;
 hints.ai_socktype=SOCK_STREAM;
 hints.ai_flags=AI_PASSIVE;


 if((rv=getaddrinfo(NULL,"8888",&hints,&servinfo))!=0)
 {      printf("\n Error 1 \n"); return 0; }


for(p=servinfo;p!=NULL;p=p->ai_next)
{

 if((sockfd=socket(servinfo->ai_family,servinfo->ai_socktype,0))==-1)
 {      perror("socket"); continue;}

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

  break;
}
 if(p==NULL)
{
 fprintf(stderr,"failed to bind");
 return 0;
}

  listen(sockfd,8);

  printf("\n\n Waiting for connection....\n");

  socklen_t size=sizeof(client_addr);

  if((connfd=accept(sockfd,(struct sockaddr *)&client_addr,&size))<0)
  {     printf("\n Error 4 \n"); return 0; }
  else
  {
       char ch[50];
       inet_ntop(AF_INET6,&(client_addr.sin6_addr),ch,50);
       printf("\n Connected to %s \n",ch);
  }

  close(sockfd);
  close(connfd);

  return 0;
}

客户代码:

#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<unistd.h>
#include<netdb.h>
int main()
{
 int i,s;

 struct addrinfo hints,*res,*p;

 memset(&hints,0,sizeof (hints));

 hints.ai_family=AF_INET6;
 hints.ai_socktype=SOCK_STREAM;

 i=getaddrinfo("fe80::20c:29ff:fe60:7593%eth0","8888",&hints,&res);//because the system in which server code is has IPv6 address fe80::20c:29ff:fe60:7593

 if(i!=0)
  { printf("\n Fail 1 \n"); return 0;}

 for(p=res;p!=NULL;p=p->ai_next)
 { 
   if((s=socket(res->ai_family,res->ai_socktype,0))==-1)
    {perror("socket"); continue;}

   if(connect(s,p->ai_addr,p->ai_addrlen)==-1)
    { close(s); perror("connect"); continue;}

   break;
 }

 if(p==NULL)
 {
  fprintf(stderr,"failed to connect\n");
   return 0;
  }

 close(s);
 return 0;
}
4

2 回答 2

2

首先,你能ping通那个本地链接地址吗?
其次,您正在填充 res 结构,然后对其进行迭代,但是在您的 for 循环中,您始终使用 res 结构进行 socket() 调用,而不是 p,它是您的迭代器。
它应该是这样的:

for(p=res;p!=NULL;p=p->ai_next)
 { 
   if((s=socket(p->ai_family,p->ai_socktype,p->ai_protocol))==-1)
    {perror("socket"); continue;}

   if(connect(s,p->ai_addr,p->ai_addrlen)==-1)
    { close(s); perror("connect"); continue;}

   break;
 }

您可能已经注意到 socket() 调用的最后一个参数不是 0,而是p->ai_protocol. 由于您只想处理 ipv6 连接并且您在提示结构中指定了您对它感兴趣的信息,因此传递它比 0 更安全。

有一个很好的做法是知道调用 getaddrinfo 出了什么问题:

if(i!=0){                                                                  
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(i));                
    return 1;                                                            
}

来自 man getaddrinfo:

gai_strerror() 函数将这些错误代码转换为人类可读的字符串,适用于错误报告。

我收到以下错误:

getaddrinfo:名称或服务未知

我检查了我无法 ping 我传递给 getaddrinfo 的地址(我传递了错误的接口)。

总而言之,我设法让您的代码正常工作。我可以从虚拟机连接到本地主机。我还指定了我们对内部提示结构感兴趣的协议:

hints.ai_protocol = IPPROTO_TCP;
于 2014-06-05T16:04:21.313 回答
0

我修复了它。实际上路由器不支持 IPv6。这就是为什么我无法从我的系统通过 ping6 ping 服务器系统。无论如何谢谢macfji :-)

于 2014-06-06T11:11:56.650 回答