sendto:网络不可达 [英] sendto: Network unreachable

查看:314
本文介绍了sendto:网络不可达的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两台机器,我测试我的代码,一个工作正常,另一个我有一些问题,我不知道为什么。



我使用一个对象(C ++)作为我的项目的网络部分。在服务器端,我这样做:(清除错误检查)

  res = getaddrinfo(NULL,port,& hints,& server))< 0 

for(p = server; p!= NULL; p = p-> ai_next){
fd = socket(p-> ai_family,p-> ai_socktype,p - > ai_protocol);
if(fd< 0){
continue;
}

if(bind(fd,p-> ai_addr,p-> ai_addrlen)< 0){
close(fd);
continue;
}
break;
}

这一切正常。然后我用这个构造函数创建一个对象

  net :: net(int fd,struct sockaddr * other,socklen_t * other_len){ 
int counter;
this-> fd = fd;
if(other!= NULL){
this-> other.sa_family = other-> sa_family;
for(counter = 0; counter <13; counter ++)
this-> other.sa_data [counter] = other-> sa_data [counter]
}
else
cerr<< 网络错误< endl;
this-> other_len = * other_len;
}

void net :: gsend(string s){
if(sendto(this-> fd,s.c_str(),s.size()+ 1 ,0,&(this-> other),this-> other_len)< 0){
cerr< Error Sending,< s < endl;
cerr<< strerror(errno)< endl;
}
return;
}

string net :: grecv(){
stringstream ss;
string s;
char buf [BUFSIZE];
buf [BUFSIZE-1] ='\0';

if(recvfrom(this-> fd,buf,BUFSIZE-1,0,0&(this-> other),&(this-> other_len))< 0) {
cerr<< Error Recieving\\\
;
cerr<< strerror(errno)< endl;
}

//转换为c ++字符串,如果有多个尾随';'删除
ss< f
s = ss.str();
while(s.find(;;,s.size() - 2)!= string :: npos)
s.erase(s.size() - 1,1);
return s;
}

所以我的问题是,在一台机器上,一切工作正常。另一方面,一切工作正常,直到我调用我的服务器的gsend()函数。在其中我得到错误:网络无法到达。我调用gsend()之前调用gercv()。谁能帮助我?非常感谢。



解决方案



事实证明,服务器不喜欢我的方式设置初始sockaddr结构。我这样做:

  struct addrinfo hints; 
memset(& hints,0,sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;
hints.ai_protocol = IPPROTO_UDP;

当它应该是这样

  struct addrinfo hints; 
memset(& hints,0,sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;

任何人都可以解释这个问题吗?

解决方案

似乎你选择你的服务器监听的接口,通过选择第一个接口,你可以创建一个套接字和绑定到?这似乎是一个新的方式来做...



当然,在有多个网卡的机器上,你很可能想绑定到一个而不是另一个,很可能知道你想要哪一个;例如,如果我们有2个NIC,一个面向互联网,一个面向内部私有网络,你可能知道你要绑定到哪个接口并提供您的服务,你的代码似乎正在做的只是选择第一个可以创建一个套接字并绑定到...



无论如何,我想在你不能从你发送的机器绑定到一个接口指向一个没有连接到你的目标地址的网络...因为你说你可以接收该套接字上的数据,并从代码片段,我假设你试图发送回你刚刚收到的地址看起来像您遇到问题时运行的机器的路由表设置不正确,并且无法从自身路由到目标机器,但目标机器可以路由到服务器...


I have two machines I'm testing my code on, one works fine, the other I'm having some problems and I don't know why it is.

I'm using an object (C++) for the networking part of my project. On the server side, I do this: (error checking removed for clarity)

     res = getaddrinfo(NULL, port, &hints, &server)) < 0

     for(p=server; p!=NULL; p=p->ai_next){
             fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
             if(fd<0){
                     continue;
                     }

             if(bind(fd, p->ai_addr, p->ai_addrlen)<0){
                     close(fd);
                     continue;
                     }
             break;
             }

This all works. I then make an object with this constructor

net::net(int fd, struct sockaddr *other, socklen_t *other_len){
        int counter;
         this->fd = fd;
         if(other != NULL){
                 this->other.sa_family = other->sa_family;
                 for(counter=0;counter<13;counter++)
                         this->other.sa_data[counter]=other->sa_data[counter];
                 }
         else
                 cerr << "Networking error" << endl;
         this->other_len = *other_len;
         }

 void net::gsend(string s){   
         if(sendto(this->fd, s.c_str(), s.size()+1, 0, &(this->other), this->other_len)<0){
                 cerr << "Error Sending, " << s << endl;
                 cerr << strerror(errno) << endl;
                 }
         return;
         }

  string net::grecv(){
         stringstream ss;
         string s;
         char buf[BUFSIZE];
         buf[BUFSIZE-1] = '\0';

         if(recvfrom(this->fd, buf, BUFSIZE-1, 0, &(this->other), &(this->other_len))<0){
                 cerr << "Error Recieving\n";
                 cerr << strerror(errno) << endl;
                 }

         // convert to c++ string and if there are multiple trailing ';' remove them
         ss << buf;
         s=ss.str();
         while(s.find(";;", s.size()-2) != string::npos)
                 s.erase(s.size()-1,1);
         return s;
         }    

So my problem is, is that on one machine, everything works fine. On another, everything works fine until I call my server's gsend() function. In which I get a "Error: Network Unreachable." I call gercv() first before calling gsend() too. Can anyone help me? I would really appreciate it.

SOLUTION

It turns out that the server didn't like the way I set up the initial sockaddr structure. I was doing this:

     struct addrinfo hints;
     memset(&hints, 0, sizeof(struct addrinfo));
     hints.ai_family = AF_UNSPEC;
     hints.ai_socktype = SOCK_DGRAM;
     hints.ai_flags = AI_PASSIVE;
     hints.ai_protocol = IPPROTO_UDP;

When it should have been like this

     struct addrinfo hints;
     memset(&hints, 0, sizeof(struct addrinfo));
     hints.ai_family = AF_UNSPEC;
     hints.ai_socktype = SOCK_DGRAM;

Can anyone explain this?

解决方案

It seems that you are picking the interface that your server listens on by selecting the first interface that you can both create a socket for and bind to? This seems a novel way to do it...

Surely, on a machine with multiple NICs you are quite likely to want to bind to one rather than another and you're likely to KNOW which one you want; for example, if we have 2 NICs, one facing the internet and one facing an internal private network you probably know which interface you want to bind to and provide your service on and what your code appears to be doing is just selecting the first that it can both create a socket for and bind to...

Anyway, I would imagine that on the machine that you cant send from you're binding to an interface that is pointing at a network that doesn't have connectivity to your target address... Since you say you can receive data on that socket and from the code snippet I assume that you're trying to send back to the address you just received from it looks like the routing table of the machine that you're running on when you're having problems is setup incorrectly and that it can't route from itself to the target machine but the target machine CAN route to the server...

这篇关于sendto:网络不可达的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆