我在编程基础2中写的基本上都是tcp的内容,这一节是有关udp的。
本节的主要内容——两个重要函数:recvfrom和sendto。
函数的声明是这样的:
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
成功时返回发送或接受的数据量,否则均返回-1。
说明:
1.如果需要知道发送者的地址,可以在recvfrom函数中提供空间,若不关心,将from指针和fromlen均值为NULL即可。
2.UDP协议没有为UDP套接字设置发送缓冲区,执行sendto时,直接将数据从用缓冲区拷到系统缓冲区,然后返回,且不保留
已经发送的内容。UDP套接字只有一个发送缓冲区大小,用来限制发送的最大UDP数据报大小,只要不超过此值,永远不会
阻塞。
3.允许发送空数据,sendto返回0。
4.UDP协议设置接收缓冲区队列,且有最大限制,超过则丢弃数据报,不发送任何错误。如果缓冲区为空,则recvfrom函数阻塞
不返回;允许接受空数据报,返回值为0(不同于TCP,收到0表示结束)。
UDP协议通信时没有连接通道,任何发送到客户机地址上的数据报将被函数recvfrom接收,不管来自谁。在客户机首次调用函数sendto
之后,它获得了本地端口号,另一个程序如果知道这个端口号,也可以向客户机发送数据报,如何才能避免呢?解决的方法就是客户机调
用函数connect。UDP套接字上调用函数connect不会产生3次握手过程,仅在该套接字中记录通信另一方的IP地址和端口号,然后函数返
回。调用了connect的UDP套接字称为连接UDP套接字。这样,连接套接字具有一些特点:
1.发送UDP数据报时不用指定服务器地址;
2.只能接收来自指定服务器的数据报;[尤其是当UDP客户机只与一个服务器通信时,最好调用connect]
3.客户机可以接收到异步错误,并且与其他UNIX系统兼容。
4.UDP套接字允许对一个套接字多次调用函数connect,TCP套接字只允许对一个套接字调用connect。
struct sockaddr_in addr1,addr2;
int udpfd;
.......
connect(udpfd,(struct sockaddr*)&addr1,sizeof(addr1));
.......
connect(udpfd,(struct sockaddr*)&addr2,sizeof(addr2));
.......
UDP套接字断开连接的操作与TCP不同,后者使用close,前者只要调用connect与它的地址断开。一般使用Posix定义的一个
特殊套接字地址来调用函数connect,该套接字的协议簇为AF_UNSPEC。
struct sockaddr_in addr;
int sockfd;
.......
addr.sin_family=AF_UNSPEC;
.......
connect(sockfd,(struct sockaddr *)&addr,sizeof(addr));
这个函数调用以错误返回,错误类型为EAFNOSUPPORT,表示UDP协议不支持AF_UNSPEC类型的套接字地址,于是将这个连接
UDP套接字记录的地址信息消除,正好。