ICMP“目的地不可达" udp连接的套接字上的数据包 [英] ICMP "destination unreachable" packet on udp connected socket

查看:359
本文介绍了ICMP“目的地不可达" udp连接的套接字上的数据包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用此功能创建了连接的UDP套接字

I've created connected UDP socket with this function

/* Creates connected udp socket */
int
udp_connect( const char *host, const char *serv)
{
    int             sockfd, n;
    struct addrinfo hints, *res, *ressave;

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

    if ( ( n = getaddrinfo( host, serv, &hints, &res)) != 0)
        err_quit( "udp_connect error for %s, %s: %s",
                 host, serv, gai_strerror(n));
    ressave = res;
    do {
        sockfd = socket( res->ai_family, res->ai_socktype, res->ai_protocol);
        if ( sockfd < 0)
            continue;   /* ignore this one */
                /* The call to connect with a UDP socket does not send anything
                 * to the peer. If something is wrong ( the peer is unreachable
                 * or there is no server at the specified port), the caller 
                 * does not discover that until it sends 
                 * a datagram to the peer */
        if ( connect( sockfd, res->ai_addr, res->ai_addrlen) == 0)
            break;      /* success */
        Close( sockfd); /* ignore this one */
    } while ( ( res = res->ai_next) != NULL);

    if ( res == NULL)   /* errno set from final connect() */
        err_sys( "udp_connect error for %s, %s", host, serv);

    freeaddrinfo( ressave);
    return( sockfd);
}

我想测试一下当对等体实际上无法访问时它的行为.由于调用connect()不能产生此信息,因此我们实际上需要发送一些信息.在以下代码段中,我将描述我的工作方式和获得的经验:

I would like to do a test how it behaves when peer is actually unreachable. Since call to connect() cannot result in this information we need to actually send something. I will describe what do I do and what do I get in the following snippet:

printf( "sending to %s\n", Sock_ntop_host( sa, salen));
// prints: sending to 127.0.0.1

Sendto( sockfd, "", 1, 0, sa, salen);   /* send 1-byte datagram */
// prints: nbytes:1
// it is sent, I check via tcpdump or with Wireshark that datagram
// has been sent and ICMP "destination unreachable" comes back from host

printf( "sent, errno:%d,%s\n", errno, strerror(errno));
// prints: sent, errno:0,Success

n = Recvfrom( sockfd, recvline, MAXLINE, 0, NULL, NULL);
// never gets here
printf( "received n=%d\n", n);

Sendto函数是sendto的包装,仅显示错误并退出:

The Sendto function is a wrapper over sendto that just prints error and exits:

void
Sendto(int fd, const void *ptr, size_t nbytes, int flags,
       const struct sockaddr *sa, socklen_t salen)
{
    if ( sendto(fd, ptr, nbytes, flags, sa, salen) == -1)
        exit(-1);//err_sys("sendto error");
    printf( "nbytes:%d\n",nbytes); // prints: nbytes:1
}

ssize_t
Recvfrom(int fd, void *ptr, size_t nbytes, int flags,
         struct sockaddr *sa, socklen_t *salenptr)
{
    ssize_t     n;

    if ( (n = recvfrom(fd, ptr, nbytes, flags, sa, salenptr)) < 0)
        err_sys("recvfrom error");
    return(n);
}

因此,当Sendto返回代码为Success的errno时,对Recvfrom的调用将永远阻塞. 然后我该如何编码以获取有关ICMP响应的通知?在没有套接字超时的情况下有可能吗?

So the call to Recvfrom blocks forever while Sendto returnes errno with code Success. How then should I code this to get notification about ICMP response? is this possible without timeout on socket?

推荐答案

一旦您connect()一个UDP套接字,就可以使用send()recv()代替sendto()recvfrom(). recv()将报告已连接套接字的ICMP错误.

Once you connect() a UDP socket, you can use send() and recv() instead of sendto() and recvfrom(). recv() will report an ICMP error for a connected socket.

这篇关于ICMP“目的地不可达" udp连接的套接字上的数据包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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