winsock简介(by 凡高娟).doc
《winsock简介(by 凡高娟).doc》由会员分享,可在线阅读,更多相关《winsock简介(by 凡高娟).doc(16页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。
1、如有侵权,请联系网站删除,仅供学习与交流winsock简介(by 凡高娟)【精品文档】第 16 页 Winsock基本知识目 录 Winsock基本知识 1. 关于网络通信Winsock是网络编程的基础,网络编程就是在计算机之间进行通信,要很好的理解网络编程我们就要从整体上把握先说说网络通信的c/s模型以及它在整个广域网上是如何实现的。1.1客户/服务器模型(c/s模型)网络应用系统通常是一个客户/服务器模型,要进行网络通信,首先我们要理解什么是c/s模型。c/s模型由两部分构成:客户端和服务器端。服务器工作的大致过程是:建立一个服务器,开启服务器使服务器处于监听状态,它检查是否有客户请求它的
2、服务;如果有客户进行请求且条件合格则接受此客户的服务请求,即建立与客户端的连接,此后双方便可以传送数据。并且服务器能同时对多个客户端提供服务。客户端工作的大致过程:客户端向服务器提出服务请求,请求连接到服务器,如果服务器接受了它的请求,则双方可以通信。一般情况下,由客户主动发起连接请求,而发起结束通信请求方则不一定。我们可以举一个简单的例子:客户与服务器的关系类似于客户和餐厅的关系。构建餐厅的房屋、招聘服务员等可以看成建立服务器,餐厅开业相当于服务器处于监听状态,等待客户的来临。客户要想进餐厅就餐,相当于客户端发起服务请求,若餐厅答应为其服务,双方就建立了连接,可以开始服务。当然一个餐厅能接受
3、多个客户。1.2.客户和服务器通过计算机网进行连接实际上,客户和服务器都是某台主机上的应用进程。运行客户进程的主机和运行服务器进程的主机分别位于不同的局域网中,这两个局域网通过路由器连接到广域网中。图1 客户和服务器主机通过广域网连接从上面的图中我们可以看到网络通信的大致过程,那么我们如何识别要找的主机,如何识别用到的进程呢?我们如何实现这些,就要看下面的winsock了,特别是套接口这一重要的概念。2. winsock到底是什么?也许你经常听到winsock这个词,那么winsock到底是什么呢?为了通信,网络也有自己的“语言,Internet的语言就是TCP/IP协议。Internet是在
4、UNIX系统上发展起来的,UNIX上一个通用的成熟的编程接口是Sockets接口。而Winsock(Windows Socket)是类似于UNIX下的Sockets,为windows系统开发的一套标准的、通用的TCP/IP编程接口。目前,Windows下的Internet软件都是在Winsock的基础上开发的。在Windows98推出以前,Winsock已经集成到windows系统中,同时包括了16位与32位的编程接口。Winsock通过c语言的动态链接库方式提供给用户和软件开发者,主要有Winsock.h头文件和动态链接库winsock.dll组成。Winsock主要经历了两个版本:Wins
5、ock1.1和Winsock2.0。Winsock2.0是Winsock1.1的扩展,它向下兼容。如果你从来没有接触过网络编程,也许从UNIX下的Sockets套接口入手更简单、直观一些,更有助于你理解网络编程。但是Winsock本身也是网络编程中很基础的部分,两个环境下的基本原理是相同的,而且程序移植很方便。由于我们的开发是在windows下进行的,所以我们在这里直接介绍Winsock。3. 网络编程最基本的概念:套接口(Socket)3.1 Socket概念无论是在UNIX环境下还是在windows环境下,Socket概念都是基础。既使你知道Socket这个词,既使你常听到人们谈到“Soc
6、ket”,而你却不知道其确切含义,它是干什么用的呢?Socket在英文中的意思是插座,通常我们称socket为套接口。套接口(Socket)是通信的基础,一个套接口是通讯的一端。在这一端上你可以找到与其对应的一个名字。一个正在被使用的套接口都有它的类型和与其相关的进程。在UNIX里,所有的东西都是文件,你的CDROM是文件,你的显示器是文件,你的硬盘也是文件,所以,你想和网络上其他程序通信的时候就要通过文件描述符。既然如此,现在你或许会想:我该怎么样得到网络通讯的文件描述符呢?你就要用到系统调用socket(),他返回套接口文件描述符,然后你可以把这个文件描述符当作普通的文件来操作。实际中,我
7、们用IP地址唯一的标识一个主机,然后根据指定的端口号找到运行在主机上的客户或服务器进程,这样我们就找到了某个特定主机上的特定进程。一个TCP连接的套接口对是一个定义该连接的两个端点的四元组:本地IP地址,本地TCP端口号,远程IP地址,远程TCP端口号。套接口对唯一标识一个互联网上的TCP连接。标识每个端点的两个值就称为一个套接口。我们了解了客户/服务器模型以及如何识别客户和服务器进程,那么具体怎样用socket实现两台计算机的连接和通信呢?3.2 socket的分类套接口可以根据通讯性质分类;这种性质对于用户是可见的。应用程序一般仅在同一类的套接口间通讯。不过只要底层的通讯协议允许,不同类型
8、的套接口间也照样可以通讯。用户目前可以使用两种套接口,即流套接口(SOCK_STREAM)和数据报套接口(SOCK_DGRAM)。流套接口提供了双向的,有序的,无重复并且无记录边界的数据流服务。数据报套接口支持双向的数据流,但并不保证是可靠,有序,无重复的。也就是说,一个从数据报套接口接收信息的进程有可能发现信息重复了,或者和发出时的顺序不同。数据报套接口的一个重要特点是它保留了记录边界。3.3 用socket实现两台计算机的通信从上面的介绍我们知道服务器和客户各有一个套接口,二者组成一个套接口对,形成一个连接进行通行,怎样建立套接口以及怎样进行通信,整个过程如下图所示: 图 2 面向连接的流
9、式套接字编程流程示意图图中的流程非常清楚,我们不再将整个流程进行文字描述,而是详细的介绍一下这些函数,它们都包含在头文件winsock.h中。3.3.1 Winsock的启动和终止应用程序在使用Windows Sockets DLL之前必须先调用函数WSAStartup()。上面的流程中我们并没有列出该函数,事实上由于winsock由DLL形式提供,为了完成一系列的初始化操作,每一个使用winsock的应用程序都必须进行WSAStartup()函数调用,并且只有在成功的完成调用之后才能使用scoket。u WSAStartup()函数函数的原形如下:int PASCAL FAR WSAStar
10、tup(WORD wVersionRequired, LPWSADATA lpWSAData);wVersionRequired表示欲使用的winsock API的版本,这是一个WORD类型的整数,它的高位字节是次版本号,低位字节是主版本号;lpWSAData是指向WSADATA结构的指针,用于返回Windows Sockets DLL的一些技术细节。如果初始化成功则函数返回0,否则返回各种错误代码。u WSACleanup():结束 Windows Sockets DLL 的使用 格式: int PASCAL FAR WSACleanup( void ); 参数: 无 返回值:成功 - 0
11、失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因) 每个WSAStartup()函数必须和一个WSACleanup()函数相对应。当应用程序终止时,必须调用WSACleanup()将自己从DLL中注销,并释放相应的资源。3.3.2 建立通信连接u socket()函数:创建套接字任何用户要进行通信都要调用socket()函数指定通信协议的类型,创建套接字。函数的原形:int socket(int family,int type,int protocol);参数参数family指明协议族,也就是利用它来分辨地址的类型,一般为AF_INET表示在Inter
12、net上的socket;type指明套接口类型,也即是通信的类型可以为SOCK_STREAM或SOCK_DGRAM;protocol参数说明该套接字使用的协议族中的特定协议,如果调用者不希望特别指定使用的协议,则置为0,使用默认的连接模式。若函数调用成功,则返回一个套接口描述字,简称套接字(sockfd);若调用失败,则返回INVALID_SOCKET。u bind()函数:指定本地地址一个套接字用socket()创建后,它其实还没有与任何特定的本地或目的地址相关联。在很多情况下,应用程序并不关心他们使用的本地地址,这时可以不调用此函数,而由协议软件为他们选择一个。如果要使用指定的端口,则创建
13、了一个套接口之后,服务器必须调用bind()函数给套接口分配一个本地协议地址,捆绑端口。函数原形:int bind(int sockfd,const struct sockaddr *myaddr,socklen_t addrlen);参数sockfd是绑定的套接字描述符,是由socket返回的;myaddr是与套接字绑定的一个本地地址结构,其长度可变,结构随协议族的不同而不同;addrlen是myaddr的长度。返回0表示函数调用成功,返回-1(SOCKET_ERROR)表示出错。u connect()函数:将套接字连接到目的地址初始创建的套接字并未与任何外地目的地址关联,客户端调用conn
14、ect()为套接字绑定一个永久的目的地址,将它置于已经连接的状态。对数据流方式的套接字,必须在传输数据前,调用connect()构造一个与目的地的TCP连接,并不能构造连接时返回一个差错代码。如果是数据报方式则不是必须在传输数据之前调用connect。函数原形:int connect(int s,const struct sockaddr *servaddr,socklen_t addrlen);s是本地套接字描述符;servaddr是指向对方套接字地址结构的指针,这里的套接口地址是服务器的套接口地址,包括服务器的IP地址和端口号,指明了要连接到的服务器;addrlen是对方套接字地址结构的长
15、度。返回0表示调用成功,返回-1表示出错。u listen()函数:设置等待连接状态对于一个服务器的程序,当申请到套接字,并调用bind()与本地地址绑定后,就应该等待某个客户机的请求连接。函数listen()就是把套接字置为这种状态,它仅被服务器调用,它使服务器的套接口成为一个监听套接口。事实上当用socket()函数建立一个套接口时,它是一个主动套接口,也就是说它应该调用connect()函数向服务器发起连接的套接口,函数Listen()将此套接口转变为被动套接口,使它接受客户向它发出的连接请求。函数原形:int listen(int sockfd,int backlog); 参数sock
16、fd是套接字描述符;backlog是指明等待连接的队列的最大长度,可以取1-5。返回0表示调用成功,返回-1表示出错。u accept()函数:接收连接请求服务器进程使用系统调用socket,bind和listen创建一个套接字,将它绑定到知名的端口,并指定连接请求的队列长度,进入监听状态,当有连接请求到达时,服务器调用accept()接收连接请求,它返回一个新建立的连接。函数原形:int accept(int sockfd,struct sockaddr * cliaddr,socklen_t *addrlen);参数sockfd是套接字描述符;指针cliaddr用于返回请求连接的客户方套接
17、字地址;指针addrlen用于返回该地址结构的长度。如果没有发生错误,则返回新的套接字,否则返回INVALID_SOCKET。值得注意的一点是,当accept()执行成功,它的返回值是内核自动生成的一个全新的描述字,它与客户进行数据通信,我们称之为会话套接口。accept()参数中的scokfd是监听套接口,accept()返回的套接口是一个已经连接到某个客户套接字的已连接套接口(会话套接口)。我们一定要区分这两种套接口。一个服务器只生成一个监听套接口且一直存在,直到服务器关闭。内核则是为每个被接受的客户创建一个已连接套接口,服务器完成客户的服务时,关闭与之通信的已连接套接口。我们可以看下面的
18、图示来更好的区分这两种套接字。 图 3 accept()函数接收请求,建立新的套接字从图中我们能够很清楚的看到,与客户进行通信的套接口并不是listenfd,而是新建立的connfd套接口。listenfd套接口继续监听,检查是否有新的连接请求,如果有新的客户请求连接,则再通过accept调用建立一个新的套接口。3.3.3 发送和接收数据当服务器端和客户端建立连接以后,就可以在两台机器之间传送数据,也即是用winsock API函数在两台连接成功的机器之间进行通信。下面我们介绍几个传送数据的函数,无论是客户端,还是服务器端都可以使用这些函数:在数据流方式中,一个连接建立以后,或者在数据报方式下
19、,调用了connect()进行了套接字与目的地址的绑定后,就可以调用send()和recv()进行数据传输。u send():使用连接好的 Socket 发送数据 格式: int send( SOCKET s, const char FAR *buf, int len, int flags );参数 s是Socket 的识别码;buf指向发送缓冲区的首址;len是缓冲区的长度; flags指定传输控制的方式,一般设为0。 传回值: 成功 - 送出的数据的长度 失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因) 此函数适用于连接式的 Datagram 或
20、 Stream Socket 来传送资料。 对 Datagram Socket 而言,若是 datagram 的大小超过限制,则将不会送出任何资料,并会传回错误值。u recv():自 Socket 接收数据 格式: int recv( SOCKET s, char FAR *buf, int len, int flags );参数s是Socket 的识别码;指针buf指向接收缓冲区的首址;len是buf 的长度 ;flags指定传输控制的方式,一般设为0。 传回值: 成功 - 接收到的数据长度 (若对方 Socket 已关闭,则为 0) 失败 - SOCKET_ERROR (呼叫 WSAGe
21、tLastError() 可得知原因) 此函数适用于连接式的 Datagram Socket 或 Stream Socket。对 Stream Socket而言,我们可以接收到目前有效的 数据,但其数量不超过 len 的大小。对 Datagram Socket 言,只取出第一个 datagram;若是该 datagram 大于使用者提供的储存空间,那么只有该空间大小的资料被取出,多余的资料将丢失,且回复错误信息。如果我们以数据报的方式通信,由于事先不用建立连接,所以可以跳过connect()而直接用recvfrom()和sendto()两个函数进行通信:u recvfrom():读取一个 Da
22、tagram,并储存数据来源的地址。格式: int recvfrom( SOCKET s,char FAR *buf,int len,int flags, struct socketaddr FAR *from,int FAR*fromlen );参数s,buf,len,flags与send()中的相同;指针from返回数据发送者的地址;fromlen是from 的大小。传回值: 成功 - 接收到的数据长度 (若对方 Socket 已关闭,则为 0) 失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因) 对 Stream Socket而言,其作用与 re
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- winsock简介by 凡高娟 winsock 简介 by 凡高娟
限制150内