16、网络套接字编程
16.1、计算机网络基础
计算机网络技术是计算机技术和通信技术相结合的产物,代表计算机的一个重要发展方向。了解计算机的网络结构,有助于用户开发网络应用程序。
16.1.1、IP地址
为了使网络上的计算机能够彼此识别对方,每台计算机都被赋予了一个独一无二的IP地址。IP地址使用IP协议规定的32位二进制表示,最新的IPv6协议已将IP地址升级为128位。这使得IP地址范围更加广泛,未来能很好地缓解IP地址紧缺的压力。目前,IPv6协议距离实际应用还有一段距离,多数操作系统和应用系统仍然以32位的IP地址为基准。
32位的IP地址主要分为前缀和后缀两部分。前缀表示计算机所属的物理网络,后缀用于确定该网络上的唯一一台计算机。在互联网上,每一个物理网络都有唯一的网络号,根据网络号的不同可以将IP地址分为5类,即A类、B类、C类、D类和E类。其中,A类、B类和C类属于基本类,D类用于多播发送,E类属于保留类,IP地址范围如下所示:
注:IP地址有几个特殊的,具有单独用途:
1、网络地址:主机地址为0的表示网络地址,如128.111.0.0
2、广播地址:在网络号后跟所有位全是1的IP地址,表示广播地址。
3、回送地址:127.0.0.1表示回送地址,用于测试。
16.1.2、OSI七层参考模型
开放系统互联(open system interconnection,OSI)是国际标准化组织(ISO)为了实现计算机网络的标准化而颁布的参考模型。OSI参考模型将网络中的数据传输划分为7层,每一层使用下层的服务,并向上层提供服务,描述OSI参考模型的结构如下所示:
OSI参考模型的建立,不仅创建了通讯设备之间的物理通道,还规划了各层之间的功能,为标准化组合和生产厂家制定好协议提供了基本依据,有助于用户了解复杂的协议,如TCP/IP,X.25协议等。
用户可以将这些协议与OSI协议参考模型对比,从而了解协议的工作原理。
16.1.3、地址解析
所谓的地址解析,是指将计算机的协议解析为物理地址,即MAC(Medium Access Control)地址,又称为媒体访问控制地址。通常,在网络上由地址解析协议(ARP)来实现地址解析。例:
假设主机A和主机B处于同一个物理网络上,主机A的IP地址为192.168.1.21,主机B的IP地址为192.168.1.23,当两台主机通信时,主机B的IP地址192.168.1.23将按如下步骤解析为物理地址。
1、主机A从本地ARP缓存中查找IP地址192.168.1.23对应的物理地址,用户可以在命令行窗口中输入"arp-a"命令查看本地ARP缓存如下所示:
2、如果主机A在ARP缓存中没有发现192.168.1.23映射的物理地址,将发送ARP请求帧到本地网络上的所有主机,在ARP请求帧中包含了主机A的物理地址和IP地址。
3、本地网络上的其他主机接收到ARP请求帧后,检查是否与自己的IP地址匹配,如果不匹配,则丢弃APR请求帧,如果主机B发现与自己的IP地址匹配,则将主机A的物理地址和IP地址添加到自己的ARP缓存中,然后主机B将自己的物理地址和IP地址发送给主机A,当主机A接收到主机B发来的信息后,将用这些信息更新ARP缓存。
4、主机B的物理地址确定后,主机A就可以与主机B通信了。
16.1.4、域名解析
虽然使用IP地址可以标识网络中的任意一台计算机,但由于IP地址容易混淆,并且不容易记忆,人们更倾向于使用主机名来标识IP地址,在internet上存在许多计算机,为了防止主机名相同,internet管理机构采取在主机名后加后缀名的方法标识一台主机,该后缀名被称为域名。例如,www.mingrisoft.com,主机名为www,域名为mingrisoft.com。这里的域名被称为二级域名,其中com为一级域名,表示商业组织,mingrisoft为本地域名。为了能够利于域名进行不同主机间通信,需要将域名解析为IP地址,称为域名解析。域名解析是通过域名服务器来完成的。
假如主机A的本地域名服务器是dns.local.com,根域名服务器是dns.mr.com;所要访问的主机B的域名为www.mingribook.com,域名服务器为dns.mrbook.com。
1、当主机A通过域名www.mingribook.com访问主机B时,将发送解析域名www.mingribook.com的报文,本地域名服务器收到请求后,首先查询本地缓存,如果没有该记录,则向根域名服务器dns.mr.com发出请求,要解析域名www.mingribook.com。
2、根域名服务器dns.mr.com收到请求后查询本地记录,如果发现mingribook.com NS dns.mr.com信息,将给出dns.mingribook.com的IP地址,并将结果返回给主机A的本地域名服务器dns.local.com。
3、当本地域名服务器dns.local.com收到信息后,会向主机B的域名服务器dns.mingribook.com发送解析域名dns.mingribook.com的报文。
4、域名服务器dns.mingribook.com收到请求后,开始查询本地记录,发现www.mingribook.com A211.120.X.X类似的信息,将结果返回给主机A的本地域名服务器dns.local.com,其中211.120.X.X表示域名dns.mingribook.com的IP地址。
16.1.5、TCO/IP协议
TCP/IP,传输控制协议/网际协议,是互联网上最流行的协议,它能够实现互联网上不同类型操作系统间的相互通信。对于网络开发人员,必须了解TCP/IP协议的结构。TCP/IP协议将网络分为4层,分别对应于OSI参考模型的7层结构。如下所示:
由上可知,TCP/IP不是单个协议,而是一个协议族,包含多种协议,其中最主要的协议是网际协议(IP)二回传输控制协议(TCP)。
1、TCP协议
传输控制协议(TCP)是一种提供可靠数据传输的通用协议,它是TCP/IP结构中传输层上的协议。在发送数据时,应用层的数据传输到传输层,加上TCP的首部,数据就构成了报文。报文是网际层IP的数据,如果再加上IP首部,就构成了IP数据报,TCP协议的C语言数据描述如下:
2、IP协议
IP协议又称为网际协议,它工作在网络层,主要提供无链接数据报传输。IP协议不保证数据报的发送,但可以最大限度地发送数据。IP协议的C语言数据描述如下:
3、ICMP协议
ICMP协议又称为网际控制报文协议。它负责网络上设备状态的发送和报文检查,可以将某个设备的故障信息发送到其他设备上。ICMP协议的C语言数据描述如下:
4、UDP协议
用户数据报协议(UDP)是一个面向无连接的协议,采用该协议,两个应用程序不需要先建立连接。它为应用程序提供一次性的数据传输服务。UDP协议不提供差错恢复,不能提供数据重传,因此该协议传输数据安全性略差。UDP协议的C语言数据描述如下:
16.1.6、端口
虽然计算机可通过IP地址标识自己,但两台计算机的实际通讯过程中,仍然存在一些问题:假设主机A中的应用程序A1想与主机B中的应用程序B1通信,如何知道是主机A中的A1应用程序而不是其他应用程序与主机B中的应用程序通信呢?当主机B接收到数据时,它又该如何知道数据是发往应用程序B1(此时主机B可能同时运行着多个程序)的呢?
为了解决上述问题,TCP/IP协议提出了"端口"概念,用于标识需要具体通信的应用程序。当应用程序(进程)与某个端口绑定后,系统会将收到的给该端口的数据送往该应用程序。端口通常用一个16位的无符号整数值表示,范围为0---65535,其中,低于256的端口是系统保留端口,用于系统进程的通信;其他端口则是自由端口,可以由进程自由使用。
16.1.7、套接字的引入
美国加利福尼亚大学的伯克利分校在UNIX上推出了一种应用程序访问通讯协议的操作系统调用套接字(socket)。socket的出现,使得程序员可以很方便地访问TCP/IP,进而开发各种网络应用程序。后来套接字被引入Windows操作系统,成为网络应用程序开发的有效工具。
套接字存在于通信区域中,通信区域也称为地址族,它将通过套接字通信的进程的共有特性综合在一起,套接字通常只与同一区域的套接字交换数据,Windows socket只支持一个通信区域------AF_INET网际域,使用网际协议族通信的进程使用该域。
16.1.8、网络字节的顺序
不同的计算机存放多字节值的顺序不同,有的机器在起始地址存放低位字节,有的机器在起始地址存放高位字节。例如,基于Inter CPU的PC机采用低位先存的方式。由于不同的计算机存放数据字节的顺序不同,因此发送数据后再接收该数据,有可能无法查看接收到的数据。为了保证数据的正确性,在网络协议中需要指定网络字节顺序。TCP/IP协议使用16位整数和32位整数的高位先存格式。
16.2、套接字基础
套接字是网络通信的基本构建,最初是加利福尼亚大学伯克利分校为UNIX开发的网络通信编程接口。为了在wind操作系统上使用套接字,20世纪90年代初,微软和第三方厂商共同制定了一套标准,即Windows socket规范,简称winsock。
16.2.1、套接字概述
所谓套接字实际上是一个指向传输提供者的句柄,在winsock中,通过操作该句柄来实现网络通信和管理。简单来说,套接字就是一个假想的连接装置,其作用类似于插座,插座用于连接电器和电线,套接字用于连接程序和网络,完成通信功能。
根据性质和作用不同,套接字可以分为原始套接字、流式套接字和数据包套接字三种。
原始套接字:由winsock2规范提出,可对底层的网络传输机制进行控制。在原始套接字下接收的数据中包含IP头。
流式套接字:提供双向、有序、可靠的数据传输服务,通信前需要双方先建立连接,TCP协议采用的就是流式套接字。
数据包套接字:提供双向的数据流,但不能保证数据传输的可靠性、有序性和无重复性。UDP协议采用的就是数据包套接字。
16.2.2、基于TCP和socket编程
TCP是面向连接的、可靠的传输协议。利用TCP通信协议时,首先要建立通信双方的连接。一但建立完成,就可以进行通信。TCP提供了数据确认和数据重传的机制,以确保发送的数据能到达通信的双方。
基于TCP、面向连接的socket编程的服务端程序流程如下:
1、创建套接字(使用socket函数)
2、将创建的套接字绑定(使用bind函数)到本地的地址和端口上
3、设置套接字的状态为监听状态(使用listen函数),准备接收客户端的连接请求
4、接收请求(使用accept函数),同时返回一个用于连接的新套接字
5、使用新套接字进行通信(使用send/recv函数)
6、通信完毕,释放套接字资源(使用closesocket函数)
基于TCP、面向连接的socket编程的客户端程序流程如下:
1、创建套接字(使用socket函数)
2、向服务器发出连接请求(使用connect函数)
3、连接后,与服务器进行通信操作(使用send/recv函数)
4、释放套接字资源(使用closesocket函数)
在服务器端,调用accept函数时程序会进行等待,直到有客户端调用connect函数发送连接请求,此时服务器接收请求,服务器端与客户端就建立了连接,可以开始通信了。
注:服务器端要建立套接字,绑定到指定的主机IP和端口上,等待客户端请求。对客户端来说,在发起连接请求并被接受后,服务器端就被保存了该客户端的IP地址和端口号信息。对服务器来说,建立连接就意味着保存了客户端的IP地址和端口号信息,利用返回的套接字即可与客户端通信。
16.2.3、基于UDP的socket编程
UDP是无连接的、不可靠的传输协议。采用UDP协议通信时,不需要建立连接,可以直接向一个IP地址发送数据,但是不能保证对方能收到。
对于基于UDP、面向无连接的socket编程来说,服务器端和客户端的概念区分不是特别严格。可以把电位器端称为接收端,客户端就是发送数据的发送端。
基于UDP、面向无连接的socket编程的接收端程序流程如下:
1、创建套接字(使用socket函数)
2、将套接字绑定(使用bind函数)到一个本地地址和端口上
3、等待接收数据(使用recvfreom函数)
4、释放套接字资源(使用closesockey函数)
基于UDP、面向无连接的socket编程的发送端程序流程如下:
1、创建套接字(使用socket函数)
2、向服务器发送数据(使用sendto函数)
3、释放套接字资源(使用closesocket函数)