recv()和recvfrom()的第4个参数可以调整函数行为。
- #include <sys/types.h>
- #include <sys/socket.h>
- ssize_t recv(int s, void *buf, size_t len, int flags);
- ssize_t recvfrom(int s, void *buf, size_t len, int flags,
- struct sockaddr *from, socklen_t *fromlen);
因为UDP是按数据包接收的,我们在接收之前并不知道这个数据包有多大。一个策略是,我们准备足够大的应用程序缓存以免出错,但是这个“足够大”的概念是建立在我们对传送的数据事先有了解的情况下,比如是我们自己设计服务器端和客户端并且制定应用层协议;另外一种策略是,将一个数据包的相关信息记录在数据包的前面的一些字节中,比如说大小,这样,我们可以通过预读数据包的前面一段,得到这个数据包的相关信息,比如说大小,然后再安排缓存。
这个预读的flag就是MSG_PEEK。使用预读后,RecvQ的下一条UDP数据包信息被读出来,但是并不从RecvQ中弹出。
UDP也可以通过recvfrom()预读获得来向的远程地址,从而可以提供给比如connect()等函数使用。
需要说明的是,在Linux下(我是Debian系统)从一个n字节的UDP数据包中预读取小于n个字节的数据是完全没有问题的;但是在WinSock下会引起一个异常10040(WSAEMSGSIZE),即是说win32下recv()或者recvfrom()在这种情况下会返回-1。其异常信息大概是读取的数据长度小于数据包的长度——而这个正是我们计划中的事情。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。