C项目实践--网络协议和套接字编程

1.TCP/IP协议

TCP/IP协议是一组包括TCP协议和IP协议,UDP(User Datagram Protocol)协议,ICMP(Internet Control Message Protocol)协议和其他一些协议的协议组。

TCP/IP协议是一个四层协议,结构如图:

image

每一层负责的功能如下:

链路层:也被称之为数据链路层或网络接口层,通常包括OS中的设备驱动程序和计算机中对应的网络接口卡,它们一起处理与电缆(或其他任何传输媒体)的物理接口细节。该层包括的协议有:ARP(Address Resolution Protocol, 地址转换协议) 和 RAPP(Reverse Address Resolution Protocol,反向地址转换协议)。

网络层:也称为互联网层,负责报文分组在网络中的活动,包括IP协议(网际协议)和ICMP(Internet 互联网控制报文协议)以及IGMP(Internet 组管理协议)。

传输层:该层主要为两台主机上的应用程序提供端到端的数据通信,它分为两个不同的协议:TCP(Transport Control Protocol,传输控制协议)和UDP(User Datagram Protocol,用户数据报协议)。TCP协议提供端到端的质量得到保证的数据传输,该层负责数据的分组,质量控制和超时重发等,对于应用层来说,就可以忽略这些工作。UDP协议则只提供简单的把数据报从一端发送到另一端,至于数据是否到达或按时到达以及数据是否损坏等都必须由应用层来做。这两种协议各有各的用途。前者可用于面向连接的应用,后者在及时性服务中有着重要的用途,如网络多媒体通信等。

应用层:该层负责处理实际的应用程序细节,包括Telnet(远程登录),HTTP(World Wide Web 服务)、 SMTP(Simple Mail Transfer Protocol, 简单邮件传输协议),FTP(File Tradfer Protocol, 简单文件传输协议)和SNMP(Simple Network Management Protocol, 简单网络管理协议)等协议。

IP协议

IP层接收由更底层(网络接口层,如以太网设备驱动程序)发来的数据包,并把该数据包发送到更高层-TCP或UDP层。相反,IP层也把从TCP或UDP层接收来的数据包传送到更底层。IP数据包是不可靠的,因为IP并没有做任何事情来确认数据包是按顺序发送的或者没有被破坏。

传输控制协议(TCP)是TCP/IP协议栈中的传输层协议,它通过序列确认以及包重发机制,提供可靠的数据流发送和到应用程序的虚拟连接服务。与IP协议相结合,TCP组成了因特网协议的核心。大多数网络应用程序都在不同的机器上运行,计算机必须能够确保目的地机器上的软件程序能从源地址机器处获得数据包,以及源计算机能收到正确的回复。这是通过使用TCP的"端口号"完成的。网络IP地址和端口号结合成为唯一的标识,称之为“套接字”或“端点”。TCP在端点间建立连接或虚拟电路进行可靠通信。TCP服务提供了数据流传输,可靠性、有效流控制,全双工操作和多路复用技术等。TCP通过面向连接的,端到端的可靠数据报发送来保证可靠性。TCP的可靠机制充许设备处理丢失、延时、重复及读错的包。超时机制充许设备监测丢失包并请求重发。

用户数据报协议(UDP)是一种无连接的传输层协议,提供面向操作的简单不可靠信息传递服务。UDP协议直接工作于IP协议的顶层,UDP协议端口不同于多路应用程序,其运行是从一个单个设备到另一个单个设备。

2.套接字编程

windows Sockets是Windows OS下定义的二进制兼容的网络编程接口,用途是将网络抽象出来,使用户不需要了解网络的细节,并且可以和任何支持套接字的程序进行网络通信。套接字是一个通信的终端,它是应用程序在网络中发送或接收数据包的对象,这个对象有类型、名字可以和进程关联。套接字是通信的基石,是支持TCP/IP协议网络通信的基本操作单元。

可用的套接字类型有以下两种:

流式套接字(SOCK_STREAM)

流式套接字定义了一种面向连接、可靠的数据传输服务,数据无差错,无重复地发送,且按发送顺序接收。内设流量控制,避免数据流超限;数据被看作是字节流,无长度限制。字节流能确保以正确的顺序无重复的被送达。

数据报套接字(SOCK_DGRAM)

数据报套接字定义了一种无连接服务。数据报以独立包形式被发送,不提供无措保证,数据可能丢失或重复,并且接收顺序混乱。

windows Sockets是一组可供应用程序进行TCP/IP通信的API应用编程接口,是一组编写网络应用程序的基本API函数,如创建套接字,地址绑定,侦听连接请求,发出连接请求,接受连接请求,发送和接收数据和关闭套接字等。这些winsock2 所用API函数的声明、常数等均在winsock2.h内定义。windows sockets2所用的API函数代码的实体包含在动态链接库ws2_32.dll中,winsock2网络应用程序.exe运行时,在动态加载系统目录中的动态链接库ws2_32.dll中,即可调用这些动态进驻到内存的winsock2 API函数代码实体。为了能这样做,网络应用程序.exe中需要ws2_32.dll的符号信息及相应的符号表,这些信息应在网络应用程序时,应在"Project"中选择"Settings…",然后在弹出对话框的"Link"选项卡中的"Object/library Modules"中添加静态链接函数库 ws2_32.lib, 才能成功编译运行,或者在代码中使用: #pragma comment(lib, "ws2_32.lib").

windows套接字程序执行API函数I/O操作时有阻塞和非阻塞两种模式。在阻塞模型下,执行I/O操作的winsock函数(如accept/ send/recv等函数)在I/O操作完成前,会一直等下去,不会立即返回程序(将控制权交还给程序);而在非阻塞模型下,调用winsock函数进行I/O操作时,不管I/O有没有完成会立即返回。Socket在初始化后默认工作在阻塞模型,可以通过ioctlsocket()函数改变Socket工作模型。通常,网络应用程序在阻塞模型下使用winsock2的API库函数进行流式套接字和数据报套接字两种编程方式。下面介绍这两种编程方式:

1.无连接的通信

Socket通信分为面向连接的通信(TCP)和面向无连接的通信(UDP)。其中无连接服务器一般都是面向事务处理的,一个请求和一个应答就完成了客户程序与服务程序之间的相互作用。

数据报套接字是无连接的,它的编程过程比流式套接字模型要简单。数据报套接字编程模式使用的基本winsock函数与流式套接字模型使用的函数是一样的,而数据传输函数则和流式套接字不同,发送数据用sendto函数,接收数据用recvfrom函数。

数据报套接字通信分为如下三步:

1.服务器端和客户端都要创建一个数据报套接字

2.服务器端调用bind函数给套接字分配一个公认的端口,在开放应用程序时,这个公认端口通常是指定的。客户端同样也需要对套接字进行绑定。

3.客户端和服务器端都可以使用sendto函数发送数据,使用recvfrom函数接受数据,完成数据报传递。通信结束时调用closesocket函数关闭套接字。默认情况下,recvfrom函数处于阻塞模型,在接收到数据前,程序将不向下执行。具体如图:

image

2.面向连接的通信

流式套接字又称为会话套接字,它定义了一种可靠的面向连接的服务,实现无差错无重复的顺序数据传输。流式套接字的服务进程和客户进程在通信前必须建立各自的套接字并进行连接,然后才能对相应的套接字进行"读",“写”操作,实现数据的传输。

流式套接字通信主要分布四步:

1.要将指定协议的套接字绑定到它已知的名字上,这个名字就是本地的IP地址加端口号。这个过程通过bind函数来完成。

2.服务进程要处于侦听状态,等待任意数量的客户端连接,以便为它们的请求提供服务。服务进程必须在所绑定的名字上进行侦听。因此,需要把套接字置为侦听模式,通过listen函数来完成。

3.服务进程调用函数accept或WSAAccept准备接受来自客户端的连接。如果一个客户端这时用函数connect试图建立连接,服务进程就可以接受连接。

4.连接建立之后,服务器端和客户端之间就可以使用函数send和recv进行通信。需要说明的是,默认情况下函数recv处于阻塞模型,在接受到数据前,程序将不向下执行。具体流程如下:

image

你可能感兴趣的:(网络协议)