免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1361 | 回复: 0
打印 上一主题 下一主题

基本UDP套接口编程 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-04-07 11:01 |只看该作者 |倒序浏览

                服务器:socket(), bind(), recvfrom(), sendto()
客户端:socket(), sendto(), recvfrom(), close()
#include
ssize_t recvfrom( int sockfd, char* buff, size_t nbytes, int flags,
                  struct sockaddr* from, socklen_t* addrlen );
ssize_t sendto  ( int sockfd, char* buff, size_t nbytes, int flags,
                  struct sockaddr* from, socklen_t addrlen );
需要注意的一点是,recvfrom的最后一个参数是值-结果参数,而sendto是一个值参数。
我们可以用这两个函数构成最简单的回射服务器程序,见Unix网络编程205页。
一般来讲,大多数TCP服务器是并发的,而UDP服务器是迭代的,也就是单个进程就得处理所有客户。
这一程序有许多需要考虑的细节:
. recvfrom是一个可以被阻塞的函数,那么,对客户来讲,如果它所发送的数据没到达服务器端(后面我们可以了解到,虽然sendto成功返回,但是有可能数据并不到达服务器,这将产生一个ICMP错误,但是在未连接的情况下,它并不返回给客户),或者服务器端的响应没有到达客户,那么客户将一走阻塞于recvfrom函数。
我们可以设置超时来解决这一问题,不过仅仅设置超时还不能完全解决这一问题,因为超时还不能完全判定是上面的那种情况引起的超时。
. 我们知道,知道客户端口号的任何进程都可往客户发送数据,那么这些数据很可能与正常的服务器应答混杂。
一个简单的解决办法是客户端接受服务器的地址,并将其与我们所发往的服务器的地址进行比较,如果相同,则是服务器的应答。
这对只有单个IP的主机是好使的,但是,如果是多宿主机(多宿主机的路由功能会指定一个IP作为其外出接口),而刚好客户所发往的IP地址不是其路由功能所指定的外出接口,那么这种策略将失效。一个解决办法是得出由recvfrom返回的IP地址后,客户通过在DNS中查找服务器主要的名字来验证该主机的域名而不是它的IP地址。另一个解决方法是UDP服务器给服务器上的每个IP地址创建一个套接口,bind每个IP地址到各自的套接口,然后在所有这些套接口上使用select,再从可读的套接口给出应答。既然用于给出应答的套接口上绑定的IP地址就是客户请求的宿IP地址(否则该数据报不会投递到该套接口),这就保证应答的源地址与请求的宿地址相同。
前面我们提出sendto可能引起的ICMP消息不会返回给客户,现在给出解释。
该错误是由sendto引起的,但是sendto是成功返回的。UDP输出操作成功返回仅表示在接口输出队列中具有存放所导致IP数据报的空间,该ICMP错误直到后来才返回,所以称此错误为异步错误。
即使sendto成功返回,那么错误将由recvfrom产生,而recvfrom可以返回的仅有信息是errno值,它没有办法返回出错数据报的宿IP地址和宿UDP端口号,因此:
对于一个UDP套接口,由它引发的异步错误并不返回给它,除非它已连接。
UDP的connect函数
UDP的connect函数结果与TCP连接大相径庭:没有三路握手,内核只是检查是否存在立即可知的错误(比如一个明显不可达的旷目的地),记录对端的IP地址和端口号,然后立即返回调用进程。也就是说,它完全是一个本地操作。
对于已连接UDP套接口,与缺省的未连接的套接口相比,发生了三个变化:
1,不用再给输出指定IP地址和端口号。也就是说,不使用sendto而使用write或send。
2,不使用recvfrom,而改用read,recv或recvmsg。
3,由已连接UDP套接口引发的异步错误返回给它们所在的进程。
UDP客户进程或服务器进程仅仅在使用自己的UDP套接口与确定的唯一对端进行通信时,才可以调用connect。
拥有一个已连接UDP套接口的进程可以为下列两个目的之一再次调用connect:
1,指定新的IP地址和端口
2,断开套接口,此时我们将地址结构的地址族成员即sin_family或sin6_faimily设置为AF_UNSPEC,这可能会返回一个EAFNOSUPPORT的错误,不过没有关系。
性能上,在一个未连接的UDP套接口上的每个数据报调用sendto函数都会执行以下步骤:
1,连接套接口
2,输出第一个数据
3,断开套接口连接
然而如果显示连接的话,则会在connect后连接输出数据报:
1,连接套接口
2,输出第一个数据报
3,输出第二个数据报
4,...
UDP是缺乏流量控制的,实际上,所有数据主机均可以接受到,但是由于UDP套接口缓冲区有限,在套接口缓冲区满后将丢弃再收到的数据。其缺省大小为42080字节,我们可以通过使用SO_RCVBUF套接口选项来修改此值:
n = 220 * 1024;
setsockopt( sockfd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n) );
               
               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/94142/showart_1891875.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP