connect()后的UDP发送行为

Raj*_*u V 8 c sockets linux udp

#include <stdio.h>  
#include <errno.h>  
#include <stdlib.h>  
#include <string.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  

int main()  
{    
    struct sockaddr_in addr;  
    int fd, cnt,ret;  
    char ch = 'y',msg[] ="How are you";  

    if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) {  
        printf("Error: socket");  
        exit(1);  
    }
    printf("\nDone socket\n");  

    /* set up destination address */  
    memset(&addr,0,sizeof(addr));  
    addr.sin_family=AF_INET;  
    addr.sin_addr.s_addr=inet_addr("128.88.143.113");  
    addr.sin_port=htons(9090);  

    ret=connect(fd,(struct sockaddr *)&addr,sizeof(addr));  
    perror("Connect:");  

    while(ch == 'y'){  
        cnt =  send(fd,msg,sizeof(msg),0);  
        if(cnt < 0)  
        perror("send:");  
        printf("\nNumber of bytes sent = %d , \n",cnt);  
        printf("Continue (y/n)\n");  
        scanf(" %c",&ch);  

     }

     return 0;  
}  
Run Code Online (Sandbox Code Playgroud)

上面的代码编译为在Linux机器上运行.

假设上面的代码将数据发送到IP地址的机器128.88.143.113.没有UDP套接字绑定到端口9090128.88.143.113.

while循环中,第一次调用send()成功(数据包实际上在线上;使用它检查trace),第二次调用send()失败Connection refused.third send()成功和第四次失败等等.

我怀疑在第一次send()堆栈收到ICMP错误消息(在tcpdumpLinux机器上看到)后保存在套接字结构中.第二个send()在看到此错误时失败,并且实际上没有发送任何数据包.第二个send()也清除套接字结构中的错误.因此,第三个send()成功,第四个成功,等等.

问题:

  1. 这个假设是否正确?
  2. 什么应该是正确的行为?是否存在定义此类行为的RFC标准?
  3. 由于UDP不维护任何连接状态,不应该每次都send()成功吗?

Has*_*kun 5

根据udplinux手册页:

即使没有连接套接字,所有致命错误也会在错误返回时传递给用户.这包括从网络接收的异步错误.您可能会收到在同一套接字上发送的早期数据包的错误.此行为不同于许多其他BSD套接字实现,除非连接套接字,否则不会传递任何错误.RFC的行为是由RFC 1122强制执行的.

具体而言,RFC(4.1.3.3)规定:

UDP必须将从IP层接收的所有ICMP错误消息传递给应用层.从概念上讲,这可以通过向ERROR_REPORT例程的上行调用来完成


use*_*421 1

从另一端开始,如果您连接 UDP 套接字,则可以在下一次发送时收集错误。如果您不想这样,请不要连接!