一、UDP的connect函数,并不进行3次握手机制,而仅仅是指定了目的ip和port而已。对于已经connect过的套接口
(1)不能再使用sendto或recvfrom函数,因为connect已经指定ip和port,所以只能用write和read函数。
(2)UDP中,connect可以多次使用,也可以断开connect后重新指定ip和port。。设置地址族为AF_UNSPEC,再调用
connect,则可以断开此接口。
实际上,sendto的操作即是循环 连接套接口,输出数据,关闭套接口 这3个动作的。
(3)一个socket只能connect一个目的主机。仅在进程用udp套接口与确定的唯一对方进行通信时,才调用connect。
二、
UDP中 ,长度为0的数据包是可以发送的,会生成一个包含IP头部(ipv4-20字节,ipv6-40字节),和8字节UDP头部,以及没有数据的
IP数据包,recvfrom返回0。
所以,当recvfrom返回0,并不意味着对方关闭了连接。实际上,UDP本来就没有连接可言。
TCP服务器一般是并发多进程的,UDP服务器一般是迭代的 。。
如果服务端进程未开启,那么客户端往其发送udp数据包时,会返回ICMP不可到达错误,但是这个错误一般不返回到客户端进程,因为ICMP不可到达错误
是异步错误,如果客户端发送多个UDP,其中一个返回错误,内核是无法判断这个错误属于哪个数据包的。
只有当客户端使用connect与服务端建立unp连接时,ICMP不可到达错误才会返还给客户端进程,具体地说是在客户端recv或者read时读取到
这个 ICMP错误。
#include
int main(int argc, char **argv) {
struct sockaddr_in ser;
int fd;
char str[20];
bzero(&ser, sizeof(struct sockaddr_in));
ser.sin_family=AF_INET;
ser.sin_port=htons(9877);
inet_pton(AF_INET, "127.0.0.1", &ser.sin_addr);
fd=socket(AF_INET, SOCK_DGRAM, 0);
if (connect(fd, (struct sockaddr *)&ser, sizeof(struct
sockaddr_in))<0)
perror("connect:");
if (sendto(fd, "ok", 3, 0, (struct sockaddr*)&ser, sizeof(struct
sockaddr_in))<0)
perror("sendto:");
if (recvfrom(fd, str, 10, 0, NULL, NULL)<0)
perror("recvfrom:");
}
如果服务器未开启的话,那么会有如下输出 recvfrom:: Connection refused
而如果没有connect进行udp连接的话,那么进程就会一直阻塞在recvfrom。。。
阅读(5375) | 评论(0) | 转发(1) |