1、第12章 WinSock网络程序设计 第12章 WinSock网络程序设计 12.1 WinSock的基本情况的基本情况 12.2 套接字编程基本概念套接字编程基本概念 12.3 Sockets库函数库函数 12.4 典型套接字系统调用时序图典型套接字系统调用时序图 12.5 Windows Sockets对对Berkeley Sockets的扩充的扩充 12.6 基于基于WinSock函数的网络应用程序开发函数的网络应用程序开发 12.7 使用面向对象的开发语言提供的与网络通信相关的类使用面向对象的开发语言提供的与网络通信相关的类 开发网络应用程序开发网络应用程序 12.8 使用可视化开发工
2、具的网络控件开发网络应用程序使用可视化开发工具的网络控件开发网络应用程序 第12章 WinSock网络程序设计 12.1 WinSock的基本情况的基本情况在Windows下的各种网络编程接口中,Windows Sockets脱颖而出,越来越得到大家的重视,这是因为Windows Sockets规范是一套开放的、支持多协议的Windows下的网络编程接口。从1991年的1.0版本到1995年的2.0.8版本,Windows Sockets经过不断完善并在Intel、Microsoft、Sun、SGI、Informix、Novell等公司的全力支持下,已经成为Windows网络编程事实上的标准。
3、第12章 WinSock网络程序设计 Windows Sockets API是Microsoft Windows的网络程序接口,它包括一个标准的Berkeley Sockets功能调用的集合,以及为Windows所做的重要扩充。扩充的功能调用都以WSA(Windows Sockets Asynchronous)作前缀,表明它们允许异步的I/O操作,并采用了符合Windows消息机制的网络事件异步选择机制。这些扩充有利于应用程序开发者更好地利用Windows的消息驱动特性,设计出高性能的网络程序。第12章 WinSock网络程序设计 Windows Sockets的实现一般都由两部分组成:开发组
4、件和运行组件。开发组件是供程序员开发Windows Sockets应用程序使用的,包括介绍Windows Sockets实现的文档、Windows Sockets应用程序接口(API)引入库和一些头文件。头文件WINSOCK.H是Windows Sockets最重要的头文件,包括了Windows Sockets实现所定义的宏、常数值、数据结构和函数调用接口类型。运行组件是Windows Sockets应用程序接口的动态连接库(DLL),文件名为WINSOCK.DLL,应用程序在执行时通过装入它实现网络通信功能。第12章 WinSock网络程序设计 12.2 套接字编程基本概念套接字编程基本概念
5、12.2.1 套接字套接字套接字(Socket)是网络通信的基本构件,是可以被命名和寻址的通信端点,使用中的每一个套接字都有其类型和一个与之相连的进程。套接字存在于通信区域中。通信区域也称为地址族,是一个抽象概念,主要用于把通过套接字通信的进程的共有特性综合在一起。套接字通常只与同一区域中的套接字交换数据(也可跨区域通信,但要执行某种转换进程之后才能实现)。Windows Sockets只支持一个通信区域:网际域(AF-INET),这个域被使用网际协议族通信的进程使用。第12章 WinSock网络程序设计 套接字都具有类型,是根据用户可见的通信特征进行分类的。应用程序被假定为只在同一类型的套接
6、字间通信,不过只要通信协议支持,也可在不同类型的套接字间通信。TCP/IP的Socket提供三种类型的套接字:(1)流式套接字(SOCK_STREAM):提供一个面向连接的、可靠的数据传输服务,数据无差错、无重复地发送,且按发送顺序接收。内设流量控制,避免数据流超限;数据被看作是字节流,无长度限制。文件传送协议(FTP)即使用流式套接字。第12章 WinSock网络程序设计(2)数据报式套接字(SOCK_DGRAM):提供一个无连接服务。数据包以独立包形式被发送,不提供无错保证,数据可能丢失、重复或接收顺序混乱。网络文件系统(NFS)使用数据报式套接字。(3)原始式套接字(SOCK_RAW):
7、该接口允许对较低层协议(如IP、ICMP)直接访问。常用于检验新的协议实现或访问现有服务中配置的新设备。第12章 WinSock网络程序设计 12.2.2 网间进程通信网间进程通信1.端口端口网络中可以被命名和寻址的通信端口是操作系统可分配的一种资源。按照OSI协议的描述,传输层与网络层在功能上的最大区别是传输层提供进程通信能力。从这个意义上讲,网络通信的最终地址不仅仅是主机地址,还包括可以描述进程的某种标识符。为此,TCP/IP协议提出了协议端口(protocol port,简称端口)的概念,用于标识通信的进程。第12章 WinSock网络程序设计 端口是一种抽象的软件结构(包括一些数据结构
8、和I/O缓冲区)。应用程序(进程)通过系统调用与某端口建立连接(binding)后,传输层传给该端口的数据都被相应进程所接收,相应进程发给传输层的数据都通过该端口输出。在TCP/IP协议的实现中,端口操作类似一般的I/O操作,进程获取一个端口,相当于获取本地惟一的I/O文件,可以用一般的读写原语访问。类似于文件描述符,每个端口都拥有一个叫端口号(port number)的整数型标识符,用于区别不同的端口。由于TCP/IP传输层的两个协议TCP和UDP是完全独立的两个软件模块,因此各自的端口号也相互独立。第12章 WinSock网络程序设计 端口号的分配是个重要问题,有两种基本分配方式:全局分配
9、和本地分配。全局分配是一种集中控制方式,由一个公认的中央机构根据用户需要进行统一分配,并将结果公布于众。本地分配又称动态链接,即进程需要访问传输层服务时,向本地操作系统提出申请,操作系统返回一个本地惟一的端口号,进程再通过合适的系统调用,将自己与该端口号联系起来。TCP/IP中端口号的分配综合了上述两种方式。TCP/IP将端口号分为两部分,少量的作为保留端口,以全局方式分配给服务进程,因此每个标准服务器都拥有一个全局公认的端口即周知端口(well-known port),即使在不同机器上,其端口号也相同。剩余的为自由端口,以本地方式进行分配。TCP和UDP均规定,小于256的端口号才能作为保留
10、端口。第12章 WinSock网络程序设计 2.地址地址网络通信中通信的两个进程在不同的机器上。这两个机器可能位于不同的网络,这些网络通过网络互联设备(网关、网桥、路由器等)连接。因此需要三级寻址:(1)某一主机与多个网络相连,必须指定一特定网络地址。(2)网络上每一主机应有惟一的地址。(3)每一主机上的每一进程应有在该主机上的惟一标识符。通常主机地址由网络ID和主机ID组成,在TCP/IP协议中用32位整数值表示;TCP和UDP均使用16位端口号标识用户进程。第12章 WinSock网络程序设计 3.网络字节顺序网络字节顺序不同计算机存放多字节值的顺序不同。为保证数据的正确性,在网络协议中需
11、要指定网络字节顺序。TCP/IP协议使用16位整数和32位整数的高价先存(高位字节在前,低位字节在后)格式,它们均含在协议头文件中。4.连接连接两个进程间的通信链路称为连接。连接在内部表现为一些缓冲区和一组协议机制,在外部表现出比无连接高的可靠性。第12章 WinSock网络程序设计 5.半相关半相关网络中用协议、本地地址、本地端口号三者构成的一个三元组在全局中惟一标志一个进程。这个三元组叫半相关(half-association),它指定连接一边的进程部分。6.全相关全相关一个完整的网间进程通信需要两个进程组成,且只能使用同一种高层协议。即不可能通信的一端用TCP协议通信,另一端用UDP协议
12、通信。因此一个完整的网间通信需要一个五元组来标识(协议,本地地址,本地端口号,远端地址,远端端口号),这个五元组叫相关或全相关(association),即两个协议相同的半相关才能组成一个合适的相关,或完全指定组成一个连接。第12章 WinSock网络程序设计 12.2.3 服务方式服务方式1.面向连接面向连接(虚电路虚电路)或无连接或无连接面向连接服务是电话系统服务模式的抽象,每一次完整的数据传输都要经过建立连接、使用连接、中止连接的过程。在数据传输过程中,各数据分组,但不携带目的地址,而是使用连接号(connect ID)。本质上,连接是一个管道,收发数据不但顺序一致,而且内容相同。TCP
13、协议提供面向连接的虚电路。无连接服务是邮政系统服务模式的抽象,每个分组都携带完整的目的地址,各分组在系统中独立传送。无连接服务不能保证分组的先后顺序,不进行分组出错的恢复和重传,不保证传输的可靠性。UDP协议提供无连接的数据报服务。第12章 WinSock网络程序设计 2.顺序顺序在网络传输中,两个连续报文在端到端通信中可能经过不同的路径,这样到达目的地址时的顺序可能会与发送时不同。“顺序”是指接收数据顺序与发送数据顺序相同。TCP协议提供这项服务。3.差错控制差错控制差错控制是保证应用程序接收的数据无差错的一种机制。检查差错的方法一般是采用检验“检查和(Checksum)”的方法。而保证传输
14、无差错的方法是双方采用确认应答技术。TCP协议提供这项服务。第12章 WinSock网络程序设计 4.流控制流控制流控制是在数据传输过程中控制数据传输速率的一种机制,以保证数据不丢失。TCP协议提供这项服务。5.字节流字节流字节流方式是指仅把传输中的报文看作是一个字节序列,不提供数据流的任何边界。TCP协议提供这项服务。6.报文报文接收方要保存发送方的报文边界。UDP协议提供这项服务。7.全双工全双工/半双工半双工端与端之间的数据同时以两个方向或一个方向传送。第12章 WinSock网络程序设计 8.缓存缓存/带外数据带外数据在字节流服务中,由于没有报文边界,用户进程在某一时刻可以读写任意数量
15、的字节。采用有流控制的协议时或为保证传输正确时,要进行缓存。但对某些特殊的需求,如交互式应用程序,又会要求取消这种缓存。在数据传输过程中,希望不通过常规传输方式传送给用户以便用户及时处理的一类信息称为带外数据。为了将互操作中的问题减到最小,应用程序编写者除非与现有服务互操作时要求带外数据,否则最好不要使用它。第12章 WinSock网络程序设计 12.2.4 客户机客户机/服务器模式服务器模式客户机/服务器模式在操作过程中采取主动请求方式。首先是服务器方要先启动,并根据请求提供相应的服务,具体操作如下:(1)打开一通信通道并告知本地主机,它愿意在某公认地址上接收客户请求。(2)等待客户请求到达
16、该端口。(3)接收到重复服务请求。处理该请求并发送应答信号。(4)返回第二步,等待另一客户请求。(5)关闭服务器。第12章 WinSock网络程序设计 客户方的具体操作如下:(1)打开一通信通道,并连接到服务器所在地主机的特定端口。(2)向服务器发送服务请求报文,等待并接收应答。(3)请求结束后关闭通信通道并中止。从上面描述的过程可知:(1)客户与服务器进程的作用是非对称的,因此编码不同。(2)服务进程一般是先于客户请求而启动的,只要系统运行,该服务进程一直存在,直到正常中止或强迫中止。第12章 WinSock网络程序设计 12.3 Sockets库函数库函数12.3.1 库函数综述库函数综述
17、1.套接字函数套接字函数Windows Sockets 1.1版本支持的Sockets函数如表12.1所示。第12章 WinSock网络程序设计 表表12.1 Windows Sockets 1.1版本中的版本中的Sockets函数函数第12章 WinSock网络程序设计 这些函数根据功能的不同可以分为如下几类:(1)套接字函数。此类函数包括sockets()、bind()、getpeername()、getsockname()和closesocket(),它们主要完成创建、关闭套接字功能,以及对套接字命名与名字获取。(2)网络连接函数。此类函数包括listen()、accept()、conn
18、ect()和shutdown(),它们完成网络连接(如虚电路)的建立与关闭。此类函数中有部分可能阻塞。(3)数据传输函数。此类函数包括send()、recv()、sendto()和recvfrom(),它们完成网络数据的发送与接收,全部是可以阻塞的函数。第12章 WinSock网络程序设计(4)字节定序函数。此类函数包括htonl()、htons()、ntohl()和ntohs(),它们完成主机和网络之间数据字节顺序的转换。(5)地址转换函数。此类函数包括inet_addr()、inet_ntoa(),它们完成网络字符串地址和Internet地址之间的转换。(6)套接字控制函数。此类函数包括g
19、etsockopt()、setsockopt()、ioctlsocket()和select(),它们设置/获取套接字的选项,控制/检测套接字的工作状态。其中select()函数在必要时可能阻塞。第12章 WinSock网络程序设计 套接字默认的工作模式是处于阻塞方式,一个阻塞操作可能阻塞整个Windows环境。在非抢占式优先的Windows环境中,建议使用非阻塞(异步)操作。也就是说,推荐使用Windows Sockets提供的异步选择函数代替可能阻塞的select()函数,并且用网络事件消息来驱动可能阻塞的网络连接函数(accept()和connect()数据传输函数。这样设计的Window
20、s程序能更好地工作。2.数据库函数数据库函数Windows Sockets定义了如表12.2所示的数据库函数。第12章 WinSock网络程序设计 表表12.2 Windows Sockets 1.1版本定义的数据库函数版本定义的数据库函数第12章 WinSock网络程序设计 提供这类函数的目的是为了获取网络特定的信息。在Windows Sockets实现中,可能使用了不依赖于本地数据库文件的方法(如域名服务),但是对应用程序来说,请求这些信息的格式是一致的,并且对应用程序来说是透明的。调用这些例程所获得的信息存放在由Windows Sockets实现分配的一个结构中,函数返回此结构的地址。因
21、此,应用程序可以通过此结构指针获取所需要的信息,但它不能修改此结构,也不能释放结构的任一部分。另外,对一个线程来说,Windows Sockets实现只分配了结构的一个备份,任何Windows Sockets API调用都可以修改此结构。也就是说,结构指针指向的数据只在此线程的下一次Windows Sockets第12章 WinSock网络程序设计 API调用之前才是正确的,应用程序应该在发布任何其他Windows Sockets API调用之前将任何需要的信息拷贝出来。数据库函数除了gethostname()之外都是阻塞的。在设计实现Windows Sockets应用程序时,建议使用Wind
22、ows Sockets提供的数据库函数的异步版本(见下节)。第12章 WinSock网络程序设计 3.Windows Sockets专用的增设函数专用的增设函数Windows Sockets针对Berkeley Sockets标准函数集提供了一些扩充,这些扩充主要用于允许对网络事件基于消息的异步存取。除了WSAStartup()和WSACleanup()函数之外,其他扩充的函数对于基于套接字的程序设计来说不是强制的,但为了和Windows程序设计风格一致,Windows Sockets推荐使用它们。Windows Sockets提供的Windows专用增设函数在表12.3中列出。第12章 Wi
23、nSock网络程序设计 表表12.3 Windows Sockets 1.1版本提供的版本提供的Windows专用增设函数专用增设函数第12章 WinSock网络程序设计 这些函数可以按功能分为如下几类:(1)启动与中止函数。此类函数包括WSAStartup()和WSACleanup(),它们是Windows Sockets网络程序必须使用的函数。(2)异步服务函数。此类函数包括WSAAsyncGetXByY()类的6个函数和WSACancelAsyncRequest()。WSAAsyncGet XByY()请求异步服务,WSACancelAsyncRequest()取消一个未完成的异步操作。
24、(3)异步选择函数。异步选择函数WSAAsyncSelect()允许应用程序注册一个或几个感兴趣的网络事件。第12章 WinSock网络程序设计(4)阻塞处理函数。此类函数包括WSAIsBlocking()、WSACancelBlockingCall()、WSASetBlockingHook()和WSAUnhookBlockingHook()。WSAIsBlocking()函数用来检测阻塞调用是否正在进行,而WSACancelBlockingCall()取消一个正在进行的阻塞调用。它们经常是联合起来使用的,参看下面的程序段:if(WSAIsBlocking()WSACancelBlocking
25、Call();函数WSASetBlockingHook()为应用程序设置自己的阻塞处理例程,Windows Sockets推荐下面的编程风格:第12章 WinSock网络程序设计 第12章 WinSock网络程序设计 在安装自己的阻塞处理例程时,保存先前安装的阻塞处理例程的程序实例指针,并在处理结束后恢复,这样的程序段在执行之后不会影响原来环境中的阻塞处理例程。函数WSAUnhookBlockingHook()恢复默认的阻塞处理例程。在多线程版本Windows中,没有默认的阻塞处理例程,调用此函数将关闭应用程序所有的阻塞处理例程,并使任何阻塞调用产生阻塞该调用的线程。(5)错误处理函数。此类函
26、数包括WSAGetLastError()和WSASetLastError()。第12章 WinSock网络程序设计 上面介绍的Windows Sockets API函数是Windows Sockets 1.1版本规范定义的函数标准集,任何Windows Sockets实现都支持这些函数。另外,特定的Windows Sockets实现可能提供了更为丰富的功能。在Windows Sockets规范中规定,从Windows Sockets DLL引出的附加接口的序数必须在1000以上,1000以内的序数保留给将来的Windows Sockets使用。那些使用了特定的Windows Sockets实现
27、所提供的附加接口的应用程序,可能不会在其他软件商提供的Windows Sockets上正常工作。建议在设计应用程序时,不要静态地把DLL连接到应用程序,而要使用Windows例程LoadLibary()和ProcAddress()动态连接,这样在不支持应用程序所使用的某些API函数时能够给出一个出错消息。第12章 WinSock网络程序设计 12.3.2 标准标准Sockets函数函数1.accept()accept()用于面向连接服务器。参数addr和addrlen存放客户方的地址信息。调用前addr指向一个初始值为空的地址结构,而addrlen的初始值为0;调用accept()后,服务器等
28、待从编号为s的套接字上接受客户连接请求,连接请求是客户方的connect()调用发出的。当有连接请求到达时,accept()调用将请求连接队列上的第一个客户方套接字地址及长度放入addr和addrlen,并创建一个与s有相同特性的新套接字号。新套接字号可用于处理服务器并发请求。第12章 WinSock网络程序设计 第12章 WinSock网络程序设计 2.bind()此函数用于未连接的数据报或流套接字,将一个本地地址与套接字相连接,即建立半相关。当用socket()创建一个套接字后,它存在于一名字空间(地址族),但没有赋予名字。bind()通过将一本地名字赋予一未命名的套接字,建立起套接字的本
29、地连接(主机地址/端口号)。第12章 WinSock网络程序设计 第12章 WinSock网络程序设计 3.closesocket()closesocket()关闭套接字s,并释放分配给该套接字的资源。如果s涉及一个打开的TCP连接,则该连接被释放。语法:int WSAAPI closesocket(SOCKET s);参数:s是待关闭的套接字的描述符。返回值:如果没有错误产生,closesocket()返回0,否则;返回SOCKET_ERROR。第12章 WinSock网络程序设计 4.connect()此函数用于与对等方建立一个连接。如果套接字s没有绑定,则系统赋予本地相关的惟一值,并且将
30、套接字表示为已绑定的。语法:int WSAAPI connect(SOCKET s,const struct sockaddr FAR*name,int namelen);参数:s是欲建立的本地套接字的描述符(套接字号)。name指出对方套接字地址结构的指针。namelen是name指向的socket address结构的字节数。第12章 WinSock网络程序设计 返回值:如果没有错误产生,connect()返回0;否则,返回SOCKET_ERROR。5.getpeername()此函数用于获取与套接字连接的对等方的地址,它检索与套接字s连接的对等方的名字,并存在sockaddr结构的nam
31、e域中。此函数只能用于已连接的数据报或流套接字。对于数据报套接字,只有在先前的connect()调用中指定的对等方的名字被返回,而不会返回先前的sendto()调用指定的名字。第12章 WinSock网络程序设计 语法:int WSAAPI getpeername(SOCKET s,struct sockaddr FAR*name,int FAR*namelen);参数:s是标识已连接的套接字的描述符。name是指向连接的套接字网际地址的指针,该结构由getpeername()在返回前填写,name的格式由通信发生的区域决定。namelen是指向name所指向的结构的大小的指针,返回时含有名字
32、的实际字节数。返回值:如果没有错误产生,getpeername()返回0;否则,返回SOCKET_ERROR。第12章 WinSock网络程序设计 6.getsockname()此函数用于获取套接字的本地名。它检索指定套接字描述符的当前名字,并存放于sockaddr结构的name域中。它用参数s指定一个已绑定或已连接的套接字,返回与该套接字相连的本地地址。当调用connect()函数之前没有调用bind()函数时,该调用特别有用,它提供了惟一一种用来确定系统设置的本地连接的方法。语法:int WSAAPI getsockname(SOCKET s,struct sockaddr FAR*nam
33、e,int FAR*namelen);第12章 WinSock网络程序设计 参数:s是已绑定(bind()的套接字的描述符。name是接收套接字的地址(名字)的缓冲区指针。namelen是指向name缓冲区大小的指针,返回名字的实际字节数。返回值:如果没有错误产生,getsockname()返回0;否则,返回SOCKET_ERROR。第12章 WinSock网络程序设计 7.getsockopt()此函数用来获取套接字选项。它检索与任何类型、任何状态的套接字相连的套接字选项的当前值,并把结果存入optval。选项可能在多个协议层存在,但它们总是表现在最高的“socket”层。选项影响套接字操作
34、,如一个操作是否阻塞、包的路由选择、带外数据传输等。语法:int WSAAPI getsockopt(SOCKET s,int level,int optname,char FAR*optval,int FAR*optlen);第12章 WinSock网络程序设计 参数:s为套接字描述符。level为设置选项的层,只支持SOL_SOCKET和IPPROTO_TCP。optname是指定要检索的套接字选项的名字。optval是指向查询选项返回值的缓冲区的指针。optlen是指向optval缓冲区大小的指针。返回值:如果没有错误产生,getsockopt()返回0;否则,返回SOCKET_ERRO
35、R。第12章 WinSock网络程序设计 8.htonl()此函数将一个u_long类型数(32位无符号整数)从主机字节顺序转换成TCP/IP网络字节顺序。语法:u_long WSAAPI htonl(u_long hostlong);参数:hostlong是指主机字节顺序表示的32位无符号整数。返回值:返回一个TCP/IP网络字节顺序表示的32位值。第12章 WinSock网络程序设计 9.htons()此函数将一个u_short类型数(16位无符号整数)从主机字节顺序转换成TCP/IP网络字节顺序。语法:u_short WSAAPI htons(u_short hostshort);参数:
36、hostshort是按主机字节顺序表示的16位无符号整数。返回值:返回一个TCP/IP网络字节顺序表示的16位值。第12章 WinSock网络程序设计 10.inet_addr()此函数将一个用点分表示法表示地址的字符串地址转换成网际地址in_addr形式。所有网际地址都以网络字节顺序(字节顺序从左到右)返回。语法:unsigned long WSAAPI inet_addr(const char FAR*cp);参数:cp是含有用网际标准点分表示法表示地址的字符串。返回值:如果没有错误产生,inet_addr()返回一个无符号长整数,用适合网际地址的二进制表示;否则,返回INADDR_ NO
37、NE。第12章 WinSock网络程序设计 11.inet_ntoa()此函数将一个网际地址转换成点分十进制表示法表示的字符串。它接收由参数in指定的网际地址结构,返回以点分表示法表示的地址的ASCII字符串。语法:char FAR*WSAAPI inet_ntoa(struct in_addr in);参数:in表示主机网际地址结构。返回值:如果没有错误产生,inet_ntoa()返回一个字符指针,该指针含有以点分十进制表示法表示的正文地址静态缓冲区,否则,返回NULL。第12章 WinSock网络程序设计 12.ioctlsocket()此函数控制套接字模式,它用于处在任何状态的任何套接字
38、,用来获取或检索与套接字相关的、独立于协议和通信子系统的操作参数。语法:int WSAAPI ioctlsocket(SOCKET s,long cmd,u_long FAR*argp);参数:s是套接字的描述符。cmd是在套接字s上执行的命令。argp是指向cmd命令的参数的指针。第12章 WinSock网络程序设计 返回值:成功结束则ioctlsocket()返回0;否则,返回SOCKET_ERROR。13.listen()此函数只用于流套接字,执行两个操作:若没有为s调用过bind(),则listen()完成套接字s所必需的连接;建立长度为backlog的请求连接队列来存放即将到来的连接
39、请求。语法:int WSAAPI listen(SOCKET s,int backlog);第12章 WinSock网络程序设计 参数:s标识一个本地已建立、尚未连接的套接字号,服务器愿意从它上面接收请求。backlog表示请求连接队列的最大长度,用于限制排队请求的个数,目前允许的最大值为5。返回值:如果没有错误产生,listen()返回0;否则,返回SOCKET_ERROR。第12章 WinSock网络程序设计 14.ntohl()此函数将一个u_long类型数(32位无符号整数)从TCP/IP网络字节顺序转换成主机字节顺序。语法:u_long WSAAPI ntohl(u_long net
40、long);参数:netlong是TCP/IP网络字节顺序表示的32位无符号整数。返回值:返回一个主机字节顺序表示的32位值。第12章 WinSock网络程序设计 15.ntohs()此函数将一个u_short类型数(16位无符号整数)从TCP/IP网络字节顺序转换成主机字节顺序。语法:u_short WSAAPI ntohs(u_short netshort);参数:netshort是TCP/IP网络字节顺序表示的16位无符号整数。返回值:返回一个主机字节顺序表示的16位值。第12章 WinSock网络程序设计 16.recv()此函数用于在参数s指定的已连接的数据报或流套接字上读取输入数据
41、。语法:int WSAAPI recv(SOCKET s,char FAR*buf,int len,int flags);参数:s为已连接的套接字描述符。buf是指向接收输入数据缓冲区的指针。len为buf所指向的缓冲区的长度。flags为指定调用方式,可用来与套接字相关的选项一起影响函数的功能。第12章 WinSock网络程序设计 返回值:如果没有错误产生,recv()返回总共接收的字节数;如果连接被关闭,返回0,否则,返回SOCKET_ ERROR。17.recvfrom()此函数用于在参数s指定的套接字(可能已连接)上读取输入数据,并捕获发送数据的地址,存入源地址缓冲区。语法:int W
42、SAAPI recvfrom(SOCKET s,char FAR*buf,int len,int flags,struct sockaddr FAR*from,int FAR*fromlen);第12章 WinSock网络程序设计 参数:s为已连接的套接字的描述符。buf是指向接收输入数据缓冲区的指针。len为buf所指向的缓冲区的长度。flags是指定调用方式,可用来与套接字相关的选项一起影响函数的功能。from是任选指针,指示源地址缓冲区。fromlen是任选指针,指示源地址缓冲区的长度。返回值:如果没有错误产生,recvfrom()返回收到的字节数;如果连接被关闭,返回0,否则,返回SO
43、CKET_ERROR。第12章 WinSock网络程序设计 18.select()此函数用来检测一个或多个套接字的状态。对每个套接字来说,这个调用可以请求读、写或错误状态的信息。请求给定状态的套接字集合由一个fd_set结构指示。在返回时,此结构被更新,以反映那些特定条件的套接字的子集,同时,select()返回满足条件的套接字的数目。语法:int WSAAPI select(int nfds,fd_set FAR*readfds,fd_set FAR*writefds,fd_set FAR*exceptfds,const struct timeval FAR*timeout);第12章 Wi
44、nSock网络程序设计 参数:nfds指明被检查的套接字描述符的值域,一般忽略该参数。readfds是指向要做读检测的套接字描述符集合的指针。writefds是指向要做写检测的套接字描述符集合的指针。exceptfds是指向要检测是否出错的套接字描述符集合的指针。timeout是指向select()等待的最大时间。如设为NULL,则为阻塞操作。第12章 WinSock网络程序设计 返回值:如果没有错误产生,select()返回包含在fd_set结构中已准备好的套接字描述符的总数目;否则,返回SOCKET_ ERROR。19.send()此函数用于在参数s指定的已连接的数据报或流套接字上发送输出
45、数据。语法:int WSAAPI send(SOCKET s,const char FAR*buf,int len,int flags);第12章 WinSock网络程序设计 参数:s为已建立的本地套接字的描述符。buf是指向存有发送数据的缓冲区的指针。len是buf指向缓冲区中数据的长度。flags是指定调用方式,可用来与套接字相关的选项一起影响函数的功能。返回值:如果没有错误产生,send()返回总共发送的字节数;否则,返回SOCKET_ERROR。第12章 WinSock网络程序设计 20.sendto()此函数用于在参数s指定的数据报或流套接字上向指定的目的地址发送输出数据。语法:in
46、t WSAAPI sendto(SOCKET s,const char FAR*buf,int len,int flags,const struct sockaddr FAR*to,int FAR*tolen);参数:s为已建立的本地套接字的描述符。buf是指向存有发送数据的缓冲区的指针。len是buf指向缓冲区中数据的长度。第12章 WinSock网络程序设计 flags是指定调用方式,可用来与套接字相关的选项一起影响函数的功能。to是指向目的套接字地址的任选指针。tolen是to所指向地址的长度。返回值:如果没有错误产生,send()返回总共发送的字节数;否则,返回SOCKET_ERROR
47、。第12章 WinSock网络程序设计 21.setsockopt()此函数为套接字相关的选项设置当前值,套接字可以是任何类型,可以处于任何状态。尽管选项可存在于多个协议层,但它们总是表现在最高的“socket”层。选项影响套接字操作,如加急数据是否在正常数据流中接收、广播消息是否在套接字上发送等。语法:int WSAAPI setsockopt(SOCKET s,int level,int optname,const char FAR*optval,int FAR*optlen);第12章 WinSock网络程序设计 参数:s为套接字描述符。level为选项定义的层次,只支持SOL_SOCK
48、ET和IPPROTO_TCP。optname是指定套接字选项的名字。optval是指向请求选项数据缓冲区的指针。optlen是选项数据optval缓冲区的长度。返回值:如果没有错误产生,setsockopt()返回0;否则,返回SOCKET_ERROR。第12章 WinSock网络程序设计 22.shutdown()此函数用来切断一个双向连接的接收、发送部分或全部连接。语法:int WSAAPI shutdown(SOCKET s,int how);参数:s是套接字描述符。how是断路方式,有0,1,2三种不同情况,分别是:如how为0(SD_RECEIVE),套接字上后续的接收将被禁止,这对
49、低层的协议没有影响;如how为1(SD_SEND),后续的发送数据被禁止;如how为2(SD_BOTH),将同时禁止后继数据的发送和接收。第12章 WinSock网络程序设计 返回值:如果没有错误产生,shutdown()返回0;否则,返回SOCKET_ERROR。23.socket()此函数建立一个套接字,它给指定的地址族、数据类型和协议分配一个套接字描述符以及相关的资源。根据这三个参数建立一个套接字,并将相应的资源分配给它,同时返回一个整型套接字号。因此socket()系统调用实际上指定了相关五元组中的“协议”这一元。语法:SOCKET WSAAPI socket(int af,int t
50、ype,int protocol);第12章 WinSock网络程序设计 参数:af是一种地址格式描述。现在支持的格式只有PF_INET,为ARPA网际地址格式。type描述要建立的套接字的类型。protocol说明该套接字使用的特定协议,如果调用者不希望特别指定使用的协议,则置为0,使用默认的连接模式。返回值:如果没有错误产生,socket()返回一个与建立的套接字相关的描述符;否则,返回INVALID_SOCKET。第12章 WinSock网络程序设计 12.3.3 数据库函数数据库函数1.gethostbyaddr()此函数用来通过地址获取主机信息。对于数据库函数中的getXbyY()类