本文转自【 https://blog.csdn.net/mrpre/article/details/43451775 】,有大量删改。
有时候,写UDP socket程序的时候,在调用sendto或者recvfrom的时候,会发现有Connection refused错误返回,错误码是ECONNREFUSED。
ECONNREFUSED A remote host refused to allow the network connection (typically because it is not running the requested service).
ICMP错误信息返回时,ICMP的包内容就是出错的那个原始数据包,根据这个原始数据包可以找出一个五元组,根据该五元组就可以对应到一个本地的connect过的UDP socket,进而把错误消息传输给该socket,应用程序在调用socket接口函数的时候,就可以得到该错误消息。如果一个UDP socket没有调用过connect,那么即使有ICMP数据包返回,由于socket保持了UDP的完整语义,协议栈也就不保存关于该socket和对端关联的任何信息,因此也就无法找到一个特定的五元组将错误码传给它。
为了获取udp端口不可达的情况,有2种方法:
法1:
对udp进行connect操作,并且将sendto改成send
法2:
int val = 1;
setsockopt(fd, IPPROTO_IP, IP_RECVERR , &val,sizeof(int));
参考实例代码:
int main() { int fd,ret,recv_len,size=1024; struct sockaddr_in server_addr,addr; int val = 1; server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = inet_addr("192.168.2.254"); server_addr.sin_port = htons(77); fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if(fd < 0) { perror("socket fail "); return -1; } printf("socket sucess\n"); //方法2 #if 1 setsockopt(fd, IPPROTO_IP, IP_RECVERR , &val,sizeof(int)); if(sendto(fd, "nihao", strlen("nihao"), 0, (const struct sockaddr *)&(server_addr), sizeof(struct sockaddr_in))<0) { perror("sendto fail "); return -1; } printf("sendto sucess\n"); recv_len = recvfrom(fd, revc_buf, sizeof(revc_buf), 0, (struct sockaddr *)&addr, (int *)&size); printf("recv_len:%d sucess\n"); //方法1 #elif 0 ret = connect(fd, (const struct sockaddr *) &(server_addr), sizeof (struct sockaddr_in)); if(ret < 0) { printf("connect fail\n"); return -1; } ret = send(fd, "ni hao", strlen("nihao"),0); if(ret < 0) { printf("write fail\n"); return -1; } ret = recvfrom(fd, revc_buf, sizeof(revc_buf), 0, (struct sockaddr *)&addr, (int *)&size); if(ret < 0) { printf("read fail\n"); return -1; } #endif close(fd); return 0; }
发表评论