Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1333812
  • 博文数量: 284
  • 博客积分: 3251
  • 博客等级: 中校
  • 技术积分: 3046
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-26 17:23
文章分类

全部博文(284)

文章存档

2019年(2)

2018年(5)

2015年(19)

2014年(13)

2013年(10)

2012年(235)

分类: LINUX

2012-12-21 16:31:02

 说起套接字的通讯,我们一般会想到C/S结构(客户端/服务端结构),从应用的角度来讲,确实如此,比如IM(即时通讯)服务,一台IM服务器同时与几 万的IM客户端进行着UDP数据报的通讯。但我们从套接字的编程实现,以及TCP/IP协议栈的实现原理这一层上来看,并不存在着服务端与客户端的明显区 别。
    网络上的两台主机(为简化起见,我们假设它们处于同一子网内,并能互相连通),为了建立一个UDP的通讯,一端A必须事先知道另一端B的端口(B有一个进 程可以接受UDP数据报)。即B必须先建立一个套接字,并自己为其选择一个固定的端口号,而不是让系统自动选择,并把这个端口号告知A(通过人,或者是熟 知端口)。然后A就可以通过connect系统调用,在其socket上设置好相应参数,以后每个发出的数据包的UDP首部中总标明目的地址B和其相应的 端口号;或者每发一个数据报,通过sendto传入B的地址和端口号,以确保每个发出的数据报在B端被正确的进程接收。
    而A端可以自己选择一个固定的端口号,也可以由系统自动选择,这并不重要。因为B端收到来自A端的第一个数据报后,可以从UDP首部中判断A端的端口号, 并在回应包中进行正确设置。在这样的情况下,我们一般就认为B是服务端,A是客户端。它们的唯一区别在于服务端的端口号必须是事先被客户端知道的。而客户 端的端口号的选择则相对比较随便。
    我们前面文章提到过协议栈中的函数myudp_v4_get_port可以为一个UDP套接口选择一个可以使用的端口号,也可以由我们自己选择一个端口号,然后由该函数判断是否可用。我们通过bind系统调用选择一个固定的端口号:
        int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
    sockfd是套接字描述符,会被转化为相应的套接字结构体,my_addr和addrlen是要绑定的地址和地址长度。地址包括IP地址(标明主机)和端口号(标明进程)。
    UDP协议没有自己的bind函数,直接使用了MY_INET域的通用bind函数。我们通常绑定的地址是INADDR_ANY,这是一个全零地址,表示 对本机接收地址不作限制,即对端可以通过本机的任何一个网络设备接口向本进程发送UDP数据报,这个IP地址被赋给套接字结构体的成员rcv_saddr 和saddr,这两个成员分别表示绑定的本机IP地址和发送数据报时的本机源IP地址。为INADDR_ANY,表示发送时根据对端IP地址,通过查询路 由表获得本机源IP地址。但端口必须由应用程序指定,这样才使bind系统变得有意义,当然,也可以设定端口为0,让协议栈自动选择,但这样,bind调 用不调用变得没有任何区别了(connect或myinet_sendmsg函数在发现端口没有绑定时,会执行自动绑定的)。对于端口绑定还有一个限制, 即要绑定的端口小于1024(PROT_SOCK)时,用户必须有相应的权限才能执行绑定,因为小于1024的端口一般为系统服务保留。
    最后,设置目的IP地址和目的端口为0,表示对对端不作任何限制。
阅读(1202) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~