论文部分内容阅读
摘要:阐述了Winsock的相关概念,介绍了套接字的相关技术和套接字编程原理,分析实现网络通信的面向连接的套接字编程模型和面向无连接的套接字编程模型,给出了在VC环境下利用Winsock开发网络应用程序的具体方法和程序代码,来实现面向连接的网络通信。
关键词:TCP/IP协议;套接字;网络编程;Winsock
中图分类号:TP393文献标识码:A文章编号:1009-3044(2012)20-4819-04
On the Realization of Network Communication by Implementing WinSock in VC
GAO Ling-xia
(Chongqing College of Electronic Engineering, Department of Computer Science, Chongqing 401331,China)
Abstract: This paper describes the related concepts of Winsock, introduces the related technology of socket and programming principle of socket, analysis of network communication of connection-oriented socket programming model and connectionless socket programming model. In VC environment, development of network application methods and program code , Using Winsock to realize connection of ori ented network communication.
Key words: TCP/IP protocol; socket ; network programming; winsock
为了实现C/S模型的网络编程,90年代初,由Microsoft联合了其他几家公司共同制定了一套WINDOWS下的网络编程接口[1],即Windows Sockets规范,它不是一种网络协议,而是一套开放的、支持多种协议的Windows下的网络编程接口。Socket(套接字)实际在计算机中提供了一个通信端口,可以通过这个端口与任何一个具有Socket接口的计算机通信。应用程序在网络上传输,接收的信息都通过这个Socket接口来实现。现在Socket接口几乎是TCP/IP网络标准API,很多TCP/IP的网络应用程序都是基于Socket而编写的。
虽然现在有很多工具如Web浏览器、FTP程序可以在网络上传输数据和文件,但是通过WinSock编程有更大的灵活性,并且不需关心网络连接细节。
1 Client/Server (客户机/服务器)模型
在网络编程中最常用的方案便是Client/Server (客户机/服务器)模型[2]。在这种方案中客户应用程序向服务器程序请求服务。一个服务程序通常在一个众所周知的地址监听对服务的请求,也就是说,服务进程一直处于休眠状态,直到一个客户向这个服务的地址提出了连接请求。在这个时刻,服务程序被"惊醒"并且为客户提供服务-对客户的请求作出适当的反应。通信过程如图1所示。
2套接字
套接字是网络计算机与应用程序之间发送和接收数据方式的一种抽象描述[1]。用来实现主机和主机通信的一个接口,完成主机间的通信操作。它位于协议之上,屏蔽了底层的协议,能够实现各种类型的通信操作。它是网络通信中应用程序对应的进程和网络协议之间的接口。网络应用程序调用Winsock API函数实现相互之间的通信,同时,Winsock利用下层的网络通信协议和操作系统实现实际的通信,如图2所示。
图2应用进程使用Winsock进行通信
在网络中进行通信,至少需要一对套接字,其中一个运行于客户机端,称之为ClientSocket[3];另一个运行于服务器端,称之为Ser verSocket。套接字主要有三个参数,分别为通信的目的IP地址,使用的传输层协议(TCP或UDP)和使用的端口。根据这些参数,应用层就可以和传输层通过socket接口,实现数据传输。
2.1 Windows Sockets的相关技术分析
2.1.1 Windows Sockets的版本
常用的Windows Sockets有两个版本:WinSock 1.1网络编程接口和WinSock2.2网络编程接口。WinSock1.1由动态链接库WIN SOCK.DLL支持,主要应用在Windows95中,WinSock2.2由动态链接库WINSOCK32.DLL支持,主要应用在Windows98和Win dows2000中。WinSock2.2与低版本WinSock1.1相比,主要对一些协议进行了扩充,如IPX、NETBIOS等,同时对WinSock1.1的函数完成兼容。
2.1.2阻塞与非阻塞
套接字具备两种模式[4]:阻塞和非阻塞模式。当套接字处于阻塞模式时调用高模式的函数时,需要消耗一定的时间来等待操作的完成,而当套接字处于非阻塞模式时,调用函数立即返回,但通常会出错。当一特定的WinSock API函数指出一个错误发生时,需要获取对应的错误代码,根据WinSock版本的不同,包含在不同的头文件中。
2.1.3网络字节顺序
网络字节就是网络上描述整数或浮点数的字节发送顺序(哪个字节被先发出去,哪个字节后发出去)。网络字节通常先传递高字节,而再传递低字节。而主机字节就是计算机内存中存放的整数或浮点数的方式,字节在内存中低字节在前,高字节在后。为了数据的一致性,就要把本地的数据转换成网络使用的格式,然后发送出去,接收的时候要转换成主机方式才能使用。下面的API函数将从主机字节顺序向网络字节顺序的转换: 1)htonl():参数是主机字节顺序的一个4字节数,函数返回网络字节顺序的数。
2)WSAHtonl():参数是主机字节顺序的一个4字节数,函数返回网络字节顺序的数。3)htons():参数是主机字节顺序的一个2字节数,函数返回网络字节顺序的数。
4)WSAHtons():参数是主机字节顺序的一个2字节数,函数返回网络字节顺序的数。
2.2 WinSock技术特点
2.2.1套接字的分类
套接字根据通信的性质可以分为三类,在设计网络应用程序时,根据不同的要求来选择相应的套接字,只有相同类型的套接字才能相互通信。
流套接字(SOCK_STREAM)。提供一个面向连接可靠的数据传输服务,数据无差错、无重复地发送,且按发送顺序接收。
数据报式套接字(SOCK_DGRAM)。提供一个无连接服务。数据包以独立包形式被发送,不提供无错保证,数据可能丢失或重复,并且接收顺序混乱。
原始式套接字(SOCK_RAW)。该接口允许对较低层协议,如IP、ICMP直接访问。常用于检验新的协议实现或访问现有服务中配置的新设备,一般不提供给普通用户。
2.2.2异步选择机制
Windows Sockets的异步选择机制为套接字编程提供了一种网络事件驱动的程序设计方法[4]。通过异步选择函数WSAAsyncSe lect(),可以为应用程序程序注册一个或多个感兴趣的网络事件,如读写事件、连接事件、接受请求事件等。用来注册异步消息的函数是WSAAsyncSelect函数,它请求Windows Sockets DLL在检测到套接字上发生的网络事件时,向窗口发送一个消息。它自动地设置套接字处于非阻塞工作方式,事件可以是一个或多个组合而成。
2.2.3对错误的处理
错误的发现和处理对于应用程序是非常重要的,对WinSock而言,经常会返回一下错误信息,最常见的是SOCKET_ERROR,它是一个值为-1的常量,这时可以用WSAGetLastError函数来获得一段代码,该代码可以清楚地表明错误产生的原因和类型,该函数的原型为:
Int WSAGetLastError(void);
2.3套接字编程模型
2.3.1面向连接的套接字编程模型
套接字编程分为面向连接的套接字和面向无连接套接字的两种编程模型。在面向连接的套接字模型中,服务器需要等待客户端向其提出的建立连接的申请,一旦接收到客户端的连接请求,服务器返回一个新的套接字描述符,通过该描述符调用数据传输函数可以与客户端进行数据的收发[5]。面向有连接的编程模型如图3所示。
图3面向连接的套接字模型
2.3.2面向无连接的套接字编程模型
面向无连接的编程模型相对比较简单。服务器和客户端没有明确的界限,而且是对等的关系。客户端之间首先创建一个数据报式套接字,并将其绑定到地址和端口上。客户端与服务端的数据交换通过sendto和recvfrom函数完成,在调用这两个函数时都指定对方的地址,而不用建立连接。最后,都需要调用closesocket关闭套接字。面向无连接的套接字编程模型如下图4所示。
3 WinSock实现基于TCP的客户端/服务器通信
此实例的目的是验证面向连接的通信模型,通过C 编码实现程序间的网络通信。实例分成两个程序,服务器端程序和客户端程序。
1)服务器程序主要代码
//定义两个socket变量,一个用来监听,一个用来建立连接和提供服务
SOCKET listenSocket,acceptSocket;
//设置服务器、客户的地址和端口
struct sockaddr_in serv,cliet;
listenSocket=socket(AF_INET,SOCK_STREAM,0);//创建监听流式socket
if(listenSocket==INVALID_SOCKET)
{ printf("建立socket出错 ");return 0;
}
//设置服务器地址信息
serv.sin_family=AF_INET;
serv.sin_port=htons(6666);
//设置监听端口是6666
serv.sin_addr.s_addr=htonl(INADDR_ANY);//将4字节主机字节顺序转换为网络字节顺序,INADDR_ANY为系统指定的IP地址。//将监听socket与服务器地址绑定
if(bind(listenSocket,(LPSOCKADDR)
关键词:TCP/IP协议;套接字;网络编程;Winsock
中图分类号:TP393文献标识码:A文章编号:1009-3044(2012)20-4819-04
On the Realization of Network Communication by Implementing WinSock in VC
GAO Ling-xia
(Chongqing College of Electronic Engineering, Department of Computer Science, Chongqing 401331,China)
Abstract: This paper describes the related concepts of Winsock, introduces the related technology of socket and programming principle of socket, analysis of network communication of connection-oriented socket programming model and connectionless socket programming model. In VC environment, development of network application methods and program code , Using Winsock to realize connection of ori ented network communication.
Key words: TCP/IP protocol; socket ; network programming; winsock
为了实现C/S模型的网络编程,90年代初,由Microsoft联合了其他几家公司共同制定了一套WINDOWS下的网络编程接口[1],即Windows Sockets规范,它不是一种网络协议,而是一套开放的、支持多种协议的Windows下的网络编程接口。Socket(套接字)实际在计算机中提供了一个通信端口,可以通过这个端口与任何一个具有Socket接口的计算机通信。应用程序在网络上传输,接收的信息都通过这个Socket接口来实现。现在Socket接口几乎是TCP/IP网络标准API,很多TCP/IP的网络应用程序都是基于Socket而编写的。
虽然现在有很多工具如Web浏览器、FTP程序可以在网络上传输数据和文件,但是通过WinSock编程有更大的灵活性,并且不需关心网络连接细节。
1 Client/Server (客户机/服务器)模型
在网络编程中最常用的方案便是Client/Server (客户机/服务器)模型[2]。在这种方案中客户应用程序向服务器程序请求服务。一个服务程序通常在一个众所周知的地址监听对服务的请求,也就是说,服务进程一直处于休眠状态,直到一个客户向这个服务的地址提出了连接请求。在这个时刻,服务程序被"惊醒"并且为客户提供服务-对客户的请求作出适当的反应。通信过程如图1所示。
2套接字
套接字是网络计算机与应用程序之间发送和接收数据方式的一种抽象描述[1]。用来实现主机和主机通信的一个接口,完成主机间的通信操作。它位于协议之上,屏蔽了底层的协议,能够实现各种类型的通信操作。它是网络通信中应用程序对应的进程和网络协议之间的接口。网络应用程序调用Winsock API函数实现相互之间的通信,同时,Winsock利用下层的网络通信协议和操作系统实现实际的通信,如图2所示。
图2应用进程使用Winsock进行通信
在网络中进行通信,至少需要一对套接字,其中一个运行于客户机端,称之为ClientSocket[3];另一个运行于服务器端,称之为Ser verSocket。套接字主要有三个参数,分别为通信的目的IP地址,使用的传输层协议(TCP或UDP)和使用的端口。根据这些参数,应用层就可以和传输层通过socket接口,实现数据传输。
2.1 Windows Sockets的相关技术分析
2.1.1 Windows Sockets的版本
常用的Windows Sockets有两个版本:WinSock 1.1网络编程接口和WinSock2.2网络编程接口。WinSock1.1由动态链接库WIN SOCK.DLL支持,主要应用在Windows95中,WinSock2.2由动态链接库WINSOCK32.DLL支持,主要应用在Windows98和Win dows2000中。WinSock2.2与低版本WinSock1.1相比,主要对一些协议进行了扩充,如IPX、NETBIOS等,同时对WinSock1.1的函数完成兼容。
2.1.2阻塞与非阻塞
套接字具备两种模式[4]:阻塞和非阻塞模式。当套接字处于阻塞模式时调用高模式的函数时,需要消耗一定的时间来等待操作的完成,而当套接字处于非阻塞模式时,调用函数立即返回,但通常会出错。当一特定的WinSock API函数指出一个错误发生时,需要获取对应的错误代码,根据WinSock版本的不同,包含在不同的头文件中。
2.1.3网络字节顺序
网络字节就是网络上描述整数或浮点数的字节发送顺序(哪个字节被先发出去,哪个字节后发出去)。网络字节通常先传递高字节,而再传递低字节。而主机字节就是计算机内存中存放的整数或浮点数的方式,字节在内存中低字节在前,高字节在后。为了数据的一致性,就要把本地的数据转换成网络使用的格式,然后发送出去,接收的时候要转换成主机方式才能使用。下面的API函数将从主机字节顺序向网络字节顺序的转换: 1)htonl():参数是主机字节顺序的一个4字节数,函数返回网络字节顺序的数。
2)WSAHtonl():参数是主机字节顺序的一个4字节数,函数返回网络字节顺序的数。3)htons():参数是主机字节顺序的一个2字节数,函数返回网络字节顺序的数。
4)WSAHtons():参数是主机字节顺序的一个2字节数,函数返回网络字节顺序的数。
2.2 WinSock技术特点
2.2.1套接字的分类
套接字根据通信的性质可以分为三类,在设计网络应用程序时,根据不同的要求来选择相应的套接字,只有相同类型的套接字才能相互通信。
流套接字(SOCK_STREAM)。提供一个面向连接可靠的数据传输服务,数据无差错、无重复地发送,且按发送顺序接收。
数据报式套接字(SOCK_DGRAM)。提供一个无连接服务。数据包以独立包形式被发送,不提供无错保证,数据可能丢失或重复,并且接收顺序混乱。
原始式套接字(SOCK_RAW)。该接口允许对较低层协议,如IP、ICMP直接访问。常用于检验新的协议实现或访问现有服务中配置的新设备,一般不提供给普通用户。
2.2.2异步选择机制
Windows Sockets的异步选择机制为套接字编程提供了一种网络事件驱动的程序设计方法[4]。通过异步选择函数WSAAsyncSe lect(),可以为应用程序程序注册一个或多个感兴趣的网络事件,如读写事件、连接事件、接受请求事件等。用来注册异步消息的函数是WSAAsyncSelect函数,它请求Windows Sockets DLL在检测到套接字上发生的网络事件时,向窗口发送一个消息。它自动地设置套接字处于非阻塞工作方式,事件可以是一个或多个组合而成。
2.2.3对错误的处理
错误的发现和处理对于应用程序是非常重要的,对WinSock而言,经常会返回一下错误信息,最常见的是SOCKET_ERROR,它是一个值为-1的常量,这时可以用WSAGetLastError函数来获得一段代码,该代码可以清楚地表明错误产生的原因和类型,该函数的原型为:
Int WSAGetLastError(void);
2.3套接字编程模型
2.3.1面向连接的套接字编程模型
套接字编程分为面向连接的套接字和面向无连接套接字的两种编程模型。在面向连接的套接字模型中,服务器需要等待客户端向其提出的建立连接的申请,一旦接收到客户端的连接请求,服务器返回一个新的套接字描述符,通过该描述符调用数据传输函数可以与客户端进行数据的收发[5]。面向有连接的编程模型如图3所示。
图3面向连接的套接字模型
2.3.2面向无连接的套接字编程模型
面向无连接的编程模型相对比较简单。服务器和客户端没有明确的界限,而且是对等的关系。客户端之间首先创建一个数据报式套接字,并将其绑定到地址和端口上。客户端与服务端的数据交换通过sendto和recvfrom函数完成,在调用这两个函数时都指定对方的地址,而不用建立连接。最后,都需要调用closesocket关闭套接字。面向无连接的套接字编程模型如下图4所示。
3 WinSock实现基于TCP的客户端/服务器通信
此实例的目的是验证面向连接的通信模型,通过C 编码实现程序间的网络通信。实例分成两个程序,服务器端程序和客户端程序。
1)服务器程序主要代码
//定义两个socket变量,一个用来监听,一个用来建立连接和提供服务
SOCKET listenSocket,acceptSocket;
//设置服务器、客户的地址和端口
struct sockaddr_in serv,cliet;
listenSocket=socket(AF_INET,SOCK_STREAM,0);//创建监听流式socket
if(listenSocket==INVALID_SOCKET)
{ printf("建立socket出错 ");return 0;
}
//设置服务器地址信息
serv.sin_family=AF_INET;
serv.sin_port=htons(6666);
//设置监听端口是6666
serv.sin_addr.s_addr=htonl(INADDR_ANY);//将4字节主机字节顺序转换为网络字节顺序,INADDR_ANY为系统指定的IP地址。//将监听socket与服务器地址绑定
if(bind(listenSocket,(LPSOCKADDR)