现在的位置: 首页 > 综合 > 正文

WIN SOCKET 几个方法解释的小结

2018年02月12日 ⁄ 综合 ⁄ 共 12434字 ⁄ 字号 评论关闭

WSASocket()

简述:创建一个与指定传送服务提供者捆绑的套接口,可选地创建和/或加入一个套接口组。

          #include <winsock2.h>

          SOCKET WSAAPI WSASocket ( int af, int type, int
          protocol, LPPROTOCOL_INFO lpProtocolInfo, Group g,
          int iFlags);

         
af:地址族描述。目前仅支持PF_INET格式,亦即ARPA Internet地址格式。
type:新套接口的类型描述。
protocol:套接口使用的特定协议,如果调用者不愿指定协议则定为0。
lpProtocolInfo:一个指向PROTOCOL_INFO结构的指针,该结构定义所创建套接口的特性。如果本参数非零,则前三个参数(af, type, protocol)被忽略。
g:套接口组的描述字。
iFlags:套接口属性描述。

返回值:
若无错误发生,WSASocket()返回新套接口的描述字。否则的话,返回 INVALID_SOCKET,应用程序可定调用WSAGetLastError()来获取相应的错误代码。

错误代码:
WSANOTINITIALISED                在调用本API之前应成功调用WSAStartup()。
WSAENETDOWN                 网络子系统失效。
WSAEAFNOSUPPORT                不支持指定的地址族。
WSAEINPROGRESS                一个阻塞的WinSock调用正在进行中,或者服务提供者仍在处理一个回调函数
WSAEMFILE                                无可用的套接口描述字。
WSAENOBUFS                        无可用的缓冲区空间。套接口无法创建。
WSAEPROTONOSUPPORT        不支持指定的协议。
WSAEPROTOTYPE                指定的协议对于本套接口类型错误。
WSAESOCKTNOSUPPORT        本地址族不支持指定的套接口类型。
WSAEINVAL                                g参数非法。

 

WSAIoctl()

简述:控制一个套接口的模式。

          #include <winsock2.h>

          int WSAAPI WSAIoctl(SOCKET s, DWORD
          dwIoControlCode, LPVOID lpvInBuffer, DWORD
          cbInBuffer, LPVOID lpvOutBuffer, DWORD
          cbOutBuffer, LPDWORD lpcbBytesReturned,
          LPWSAOVERLAPPED lpOverlapped,
          LPWSAOVERLAPPED_COMPLETION_ROUTINE
          lpCompletionRoutine);

s:一个套接口的句柄。
dwIoControlCode:将进行的操作的控制代码。
lpvInBuffer:输入缓冲区的地址。
cbInBuffer:输入缓冲区的大小。
lpvOutBuffer:输出缓冲区的地址。
cbOutBuffer:输出缓冲区的大小。
lpcbBytesReturned:输出实际字节数的地址。
lpOverlapped:WSAOVERLAPPED结构的地址。
lpCompletionRoutine:一个指向操作结束后调用的例程指针。

返回值:
调用成功后,WSAIoctl ()函数返回0。否则的话,将返回INVALID_SOCKET错误,应用程序可通过WSAGetLastError()来获取相应的错误代码。

错误代码:
WSANOTINITIALISED                在调用本API之前应成功调用WSAStartup()。
WSAENETDOWN                        网络子系统失效。
WSAEINVAL                                cmd不是一个合法的命令;或者一个输入参数非法;或者命令对于该种类型的套接口不适用。
WSAEINPROGRESS                在一个回调函数运行时调用了该函数。
WSAENOTSOCK                        描述字不是一个套接口。
WSAEOPNOTSUPP                指定的ioctl命令无法实现,例如在SIO_SET_QOS或                              SIO_SET_GROUP_QOS中指定的流描述无法实现。
WSA_IO_PENDING                一个重叠操作被成功启动,过后将报告完成情况。
WSAEWOULDBLOCK                套接口标志为非阻塞,且所需操作将产生阻塞。

 

 

WSAJoinLeaf()

简述:将一个叶节点加入一个多点会晤,交换连接数据,根据提供的流描述确定所需的服务质量。

          #include <winsock2.h>

          SOCKET WSAAPI WSAJoinLeaf ( SOCKET s, const struct
          sockaddr FAR * name, int namelen, LPWSABUF
          lpCallerData, LPWSABUF lpCalleeData,
           LPQOS lpSQOS, LPQOS lpGQOS, int iFlags );

         
s:标识一个多点套接口的描述字。
name:将与套接口连接的远端名字。
namelen:名字长度。
lpCallerData:一个指针,指向多点会晤创建时传送给远端的用户数据。
lpCalleeData:一个指针,指向多点会晤创建时从远端传送回来的用户数据。
lpSQOS:一个指向套接口s的流描述的指针,每个方向一个。
lpGQOS:一个指向套接口组(如果存在)流描述的指针。
iFlags:标志位,用于指定套接口作为发送者。接收者或身兼二者。

返回值:若无错误发生,WSAJoinLeaf()返回新创建的多点套接口的描述字。否则的话,将返回INVALID_SOCKET错误,应用程序可通过WSAGetLastError()来获取相应的错误代码。

错误代码:
WSANOTINITIALISED                在调用本API之前应成功调用WSAStartup()。
WSAENETDOWN                        网络子系统失效。
WSAEADDRINUSE                指定的地址已经在使用中。
WSAEINTR                                通过WSACancelBlockingCall()函数取消(阻塞)调用。
WSAEINPROGRESS                一个阻塞的WinSock调用正在进行中,或者服务提供者仍在处理一个回调函数
WSAEALREADY                        在指定的套接口上正在运行一个非阻塞的WSAJoinLeaf()调用。
WSAEADDRNOTAVAIL        本地主机无法获得指定的地址。
WSAEAFNOSUPPORT                所指定地址族中的地址无法与本套接口一起使用。
WSAECONNREFUSED                加入试图被强制拒绝。
WSAEFAULT                                name或namelen参数不是用户地址空间的一个有效部分;namelen参数太小;lpCalleeData、 lpSQOS和lpGQOS的缓冲区太小; lpCallerData缓冲区太大。
WSAEINVAL                                套接口已与一个地址捆绑。
WSAEINVAL                                套接口未与一个地址捆绑。
WSAEISCONN                        套接口已是多点会晤的一个成员。
WSAENETUNREACH                当前无法从本主机联系网络。
WSAENOBUFS                        无可用缓冲区空间。套接口无法加入。
WSAENOTSOCK                        描述字不是一个套接口。
WSAEOPNOTSUPP                 lpSQOS和lpGQOS中所指定的流描述无法满足。
WSAEPROTONOSUPPORT        服务提供者不支持lpCallerData参数。
WSAETIMEDOUT                        加入试图超时,未建立多点会晤。
WSAEWOULDBLOCK                套接口被标志为非阻塞,但多点会晤加入操作无法立即完成。当用select()选为读连接后,可使用select()对套接口进行操作。

 

WSAAsyncSelect()

简述:
        通知套接口有请求事件发生.
       
        #include <winsock.h>

        int PASCAL FAR WSAAsyncSelect ( SOCKET s, HWND hWnd,
                        unsigned int wMsg, long lEvent );
       
        s   标识一个需要事件通知的套接口的描述符.
        hWnd    标识一个在网络事件发生时需要接收消息的窗口句柄.
        wMsg    在网络事件发生时要接收的消息.
        lEvent 位屏蔽码,用于指明应用程序感兴趣的网络事件集合.
       
注释:
        本函数用来请求Windows Sockets DLL为窗口句柄发一条消息-无论它何时检测到由lEvent参数指明的网络事件.要发送的消息由wMsg参数标明.被通知的套接口由s标识.
        本函数自动将套接口设置为非阻塞模式.
        lEvent参数由下表中列出的值组成.
        值      意义
        FD_READ 欲接收读准备好的通知.
        FD_WRITE    欲接收写准备好的通知.
        FD_OOB 欲接收带边数据到达的通知.
        FD_ACCEPT   欲接收将要连接的通知.
        FD_CONNECT 欲接收已连接好的通知.
        FD_CLOSE    欲接收套接口关闭的通知.
       
        启动一个WSAAsyncSelect()将使为同一个套接口启动的所有先前的WSAAsyncSelect()作废. 例如,要接收读写通知,应用程序必须同时用FD_READ和FD_WRITE调用WSAAsyncSelect(),如下:
        rc = WSAAsyncSelect(s, hWnd, wMsg, FD_READ|FD_WRITE);
        对不同的事件区分不同的消息是不可能的.下面的代码将不会工作;第二个调用将会使第一次调用的作用失效,只有FD_WRITE会通过wMsg2消息通知到.
                        rc = WSAAsyncSelect(s, hWnd, wMsg1, FD_READ);
                        rc = WSAAsyncSelect(s, hWnd, wMsg2, FD_WRITE);

        如果要取消所有的通知,也就是指出Windows Sockets的实现不再在套接口上发送任何和网络事件相关的消息,则lEvent应置为0.
                        rc = WSAAsyncSelect(s, hWnd, 0, 0);
       
        尽管在本例中,WSAAsyncSelect()立即使传给该套接口的事件消息无效, 仍有可能有消息等在应用程序的消息队列中.应用程序因此也必须仍准备好接收网络消息-即使消息作废.用closesocket()关闭一个套接口也同样使WSAAsyncSelect()发送的消息作废,但在closesocke()之前队列中的消息仍然起作用.
        由于一个已调用accept()的套接口和用来接收它的侦听套接口有同样的属性, 任何为侦听套接口设置的的WSAAsyncSelect()事件也同样对已接收的套接口起作用.例如, 如果一个侦听的套接口有WSAAsyncSelect()事件FD_ACCEPT,FD_READ,FD_WRITE, 则任何在那个侦听的套接口上接收的套接口将也有FD_ACCEPT,FD_READ,FD_WRITE事件,以及同样的wMsg的值.若需要不同的wMsg及事件,应用程序应调用WSAAsyncSelect(),将已接收的套接口和想要发送的新消息作为参数传递.
        当某一套接口s上发生了一个已命名的网络事件,应用程序窗口hWnd会接收到消息wMsg.wParam参数标识了网络事件发生的套接口.lParam的低字指明了发生的网络事件.lParam的高字则含有一个错误代码.该错误代码可以是winsock.h中定义的任何错误.
        错误代码和事件可以通过WSAGETSELECTERRORH和WSAGETSELECTEVENT宏从lParam中取出.定义如下:
                  #define WSAGETSELECTERROR(lParam)            HIWORD(lParam)
                  #define WSAGETSELECTEVENT(lParam)            LOWORD(lParam)
注意:在accept()调用和为改变事件或wMsg的WSAAsyncSelect()调用中有一个计时窗口.应用程序如果需要给侦听的和调用过accept()的套接口以不同的wMsg,它就应该在侦听的套接口上请求FD_ACCEPT事件,然后在accept()调用后设置相应的事件.由于FD_ACCEPT从不发送给已连接的套接口,而FD_READ,FD_WRITE,FD_OOB及FD_CLOSE也从不发送给侦听套接口,所以不会产生困难.
        使用以上的宏将最大限度的提高应用程序的可移植性.
        返回的可能网络事件如下:
        值      意义
        FD_READ 套接口s准备读
        FD_WRITE    套接口s准备写
        FD_OOB 带外数据准备好在套接口s上读.
        FD_ACCEPT   套接口s准备接收新的将要到来的连接.
        FD_CONNECT 套接口s上的连接完成.
        FD_CLOSE    由套接口s标识的连接已关闭.

返回值:
        0           若应用程序感兴趣的网络事件的声明成功.
        SOCKET_ERROR    否则.可通过调用WSAGetLastError()返回特定的错误代码.

评价:
        尽管WSAAsyncSelect()可以以多个事件的组合来调用,应用程序窗口还是会为每个网络事件接收一条消息.
        如同select()函数,WSAAsyncSelect()会被频繁地调用来决定,何时一次数据转移操作(send()或recv())可以启动,并且可以立刻成功.尽管如此,健壮的应用程序必须做好这样的准备, 即它可能接收到消息及启动了一个会立即返回WSAEWOULDBLOCK的Windows Sockets API调用.例如,下列的事件序列是可能的:
        (i) 数据到达套接口s;Windows Sockets传递WSAAsyncSelect消息.
        (ii)    应用程序处理其它一些消息.
        (iii)   在处理过程中,应用程序启动了ioctlsocket(s,FIONREAD...)并且注意到有数据准备好读.
        (iv)    应用程序启动recv(s,...)来读数据.
        (v) 应用程序循环处理下一条消息,最终到达WSAAsyncSelect消息,表示数据已准备好读.
        (vi)    应用程序启动recv(s,...),但失败并有错误WSAEWOULDBLOCK.
        其它的事件序列也是可能的.
        Windows Sockets DLL不会不断地为某一特定的网络事件向一个应用程序发送消息. 如果已成功地向应用程序窗口发送了一特定事件的通知,对该应用程序窗口将不再为该网络事件发消息,直到应用程序调用函数隐含地重新通知该网络事件.
        事件        重新通知函数
        FD_READ recv()或recvfrom()
        FD_WRITE    send()或sendto()
        FD_OOB recv()
        FD_ACCEPT   accept()
        FD_CONNECT 无
        FD_CLOSE    无
        任何对重新通知函数的调用,即使失败,也会达到为相关事件发重新通知消息的效果.
        对FD_READ,FD_OOB和FD_ACCEPT事件,消息传递是"水平触发"(level-triggered)的.这意味着,若调用了重新通知函数并且相关的事件对该调用仍有效,WSAAsyncSelect()消息就将传给应用程序.这为应用程序提供了事件驱动以及不必考虑在任一时刻到达的数据量的能力.考虑下列序列:
        (i) Windows Sockets DLL在套接口s上接收100字节的数据并传递一个FD_READ消息.
        (ii)    应用程序启动recv(s,buffptr,50,0)接收50字节.
        (iii)   由于仍有数据未读,Windows Sockets DLL发送另一个FD_READ消息.
       
        根据以上语义,应用程序不必在收到FD_READ消息时读进所有可读的数据-对应于每一FD_READ消息进行一次recv()调用是恰当的.如果应用程序为一个FD_READ消息而启动了多个recv()调用,它将接收到多个FD_READ消息.这样的应用程序可能希望在开始recv()调用( 通过不为FD_READ事件置位的WSAAsyncSelect()函数调用)之前关闭FD_READ消息.
        如果在应用程序初次调用WSAAsyncSelect()或当调用了重新通知函数时,有一个事件为真, 则会发送一个相应的消息.例如,若应用程序调用listen(),就会试图进行连接,然后应用程序调用WSAAsyncSelect()声明它需要为套接口接收FD_ACCEPT消息,Windows Sockets的实现就会立即传递一个FD_ACCEPT消息.
        FD_WRITE事件处理起来稍有不同.FD_WRITE消息是在套接口第一次用connect()连接或由accept()接受,并且在send()或sendto()以WSAWOULDBLOCK错误失败后缓冲区空闲时发送的.因此,应用程序可以假设发送可能在第一次FD_WRITE消息时开始,并持续到一次返回WSAEWOULDBLOCK的发送. 在这样的失败后,应用程序将被通知,FD_WRITE消息的发送又将可能.
        FD_OOB事件只用在当套接口配置成独立接收带外数据时.如果一个套接口被配置成接收感兴趣的带外数据状态,带外数据将和普通数据等同视之,并且应用程序应该注册它感兴趣的方面,然后将接收FD_READ事件,而不是FD_OOB事件.应用程序可以设置或监控带外数据处理的方法(通过使用setsockopt()或getsockopt()函数,及SO_OOBINLINE选项).
        在FD_CLOSE消息中的错误代码指出套接口的关闭是正常的还是异常的.如果错误代码是0,则关闭是正常的;若错误代码是WSAECONNRESET,则套接口的虚套接口将被重置.这些只对SOCK_STREAM类型的套接口起作用.
        FD_CLOSE消息在相应套接口的虚电路关闭指令接收到时发送.在TCP术语中,这意味着FD_CLOSE在连接进入了FIN WAIT或CLOSE WAIT状态时发送.这是远端对发送方进行了shutdown()调用或closesocket()调用的结果.
        请注意你的应用程序将只会收到FD_CLOSE消息来指出虚电路的关闭.它不会收到FD_READ消息来表示该状况.

错误代码:
        WSANOTINITIALISED       在使用本API前必须进行一次成功的WSAStartup()调用.
        WSAENETDOWN     WINDOWS SOCKETS实现已检测到网络子系统故障.
        WSAEINVAL           指出指定的参数之一是非法的.
        WSAEINPROGRESS      一个阻塞的Windows Sockets操作正在进行.
        附加的错误代码可能在应用程序窗口接收到消息时被置.这些代码可以用WSAGETSELECTERROR宏从lParam中取出.对应于每个网络事件的可能错误代码为:
        事件:FD_CONNECT
        WSAEADDRINUSE       给定的地址已被使用.
        WSAEADDRNOTAVAIL        指定的地址在本地机器不能使用.
        WSAEAFNOSUPPORT     指定族的地址不能和本套接口同时使用.
        WSAECONNREFUSED     连接的尝试被拒绝.
        WSAEDESTADDRREQ     需要一个目的地址.
        WSAEFAULT           namelen参数不正确.
        WSAEINVAL           套接口已经约束到一个地址.
        WSAEISCONN          套接口已经连接.
        WSAEMFILE           没有可用的文件描述符.
        WSAENETUNREACH      此时网络不能从该主机访问.
        WSAENOBUFS          无可用的缓冲区空间.套接口不能连接.
        WSAENOTCONN     套接口没有连接.
        WSAENOTSOCK     该描述符是文件,不是套接口.
        WSAETIMEDOUT        试图连接超时,未建立连接.
        事件:FD_CLOSE
        WSAENETDOWN     WINDOWS SOCKETS实现已检测到网络子系统故障.
        WSAECONNRESET       连接由远端重建.
        WSAECONNABORTED     由于超时或其它失败放弃连接.
        事件:FD_READ
        事件:FD_WRITE
        事件:FD_OOB
        事件:FD_ACCEPT
        WSAENETDOWN     WINDOWS SOCKETS实现已检测到网络子系统故障.

关于Windows Sockets提供者的说明:
        Windows Sockets的提供者应确保消息可以成功地传给应用程序.如果PostMessag()操作失败,Windows Sockets的实现必须重发该消息-只要窗口存在.
        Windows Sockets提供者应使用WSAMAKESELECTREPLY宏来构造消息中的lParam参数.
        当套接口关闭时,Windows Sockets提供者应清除所有保留下来要发送给应用程序窗口的消息.然而应用程序必须准备好接收,放弃任何在closesocket()之前可能已经发送的消息.

WSASendTo()

简述:向指定地址发送数据,可能的话使用重叠输入/输出操作。

          #include <winsock2.h>

          int WSAAPI WSASendTo ( SOCKET s, LPWSABUF
          lpBuffers, DWORD dwBufferCount, LPDWORD
          lpNumberOfBytesSent, int iFlags, LPVOID lpTo, int
          iToLen, LPWSAOVERLAPPED lpOverlapped,
          LPWSAOVERLAPPED_COMPLETION_ROUTINE
          lpCompletionRoutine );

         
s:用于标识一个已连接的套接口,该套接口以WSA_FLAG_OVERLAPPED标志调用WSASocket()创建。
lpBuffers:一个指向WSABUF结构数组的指针。每个WSABUF结构包含缓冲区的指针和缓冲区的大小。
dwBufferCount:lpBuffers数组中WSABUF结构的数目。
lpNumberOfBytesSent:如果发送操作立即完成,则为一个指向所发送数据字节数的指针。
iFlags:标志位。
lpTo:(可选)指针,指向目标套接口的地址。
lpTolen:lpTo中地址的大小。
lpOverlapped:指向WSAOVERLAPPED结构的指针(对于非重叠套接口则忽略)。
lpCompletionRoutine:一个指向发送操作完成后调用的完成例程的指针。(对于非重叠套接口则忽略)。

返回值:
若无错误发生且发送操作立即完成,则WSASendTo()函数返回所发送的字节数(请注意它可能小于len所指定的值)。请注意在这种情况下完成指示(启动指定的完成例程或设置一个事件对象)将早已发生。否则的话,将返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()来获取相应的错误代码。错误代码WSA_IO_PENDING表示重叠操作成功启动,过后将有完成指示。任何其他的错误表示重叠操作未能成功地启动,以后也不会有完成指示。
如果设置了MSG_INTERRUPT标志,则返回值的含义变化。零表示成功,具体含义同上。否则的话,返回值直接包含如下所示的错误代码。由于中断环境中无法调用WSAGetLastError(),故是必需的。请注意仅适用于Win16环境,仅适用于PROTOCOL_INFO结构中设置了XP1_INTERRUPT位的协议。

错误代码:
WSANOTINITIALISED                在调用本API之前应成功调用WSAStartup()。
WSAENETDOWN                        网络子系统失效。
WSAEACCES                                请求的地址为广播地址,但未设置相应的标志位。
WSAEINTR                                 通过WSACancelBlockingCall()函数取消(阻塞)调用。
WSAEINPROGRESS                一个阻塞的WinSock调用正在进行中,或者服务提供者仍在处理一个回调函数
WSAEFAULT                                lpBuffer或lpTo参数不是用户地址空间的一部分;或者lpTo参数太小(小于sockaddr结构的大小)。
WSAENETRESET                        远端主机复位造成连接的中止。
WSAENOBUFS                        WinSock提供者报告了一个缓冲区死锁。
WSAENOTCONN                        套接口未连接(仅适用于面向连接的套接口)。
WSAENOTSOCK                        描述字不是一个套接口。
WSAEOPNOTSUPP                设置了MSG_OOB,但是该套接口不是诸如SOCK_STREAM流类型的,与套接口相关的通讯域不支持带外数据,或者套接口是单向的,只支持接收操作。
WSAESHUTDOWN                套接口已经关闭;一个套接口以SD_SEND或SD _BOTH的how参数shutdown()后,无法进行WSASendTo()调用。
WSAEWOULDBLOCK                太多重叠的输入/输出请求。
WSAEMSGSIZE                        套接口是面向消息的,且消息大于底层传送所支持的最大长度。
WSAEINVAL                                套接口未用bind()捆绑,或者套接口未用重叠标志位创建。
WSAECONNABORTED        由于超时或其他错误导致虚电路中止。
WSAECONNRESET                虚电路被远端复位。
WSAEADDRNOTAVAIL        本地主机无法获取所指定的地址。
WSAEAFNOSUPPORT                指定地址族中的地址无法与本套接口一起使用。
WSAEDESTADDRREQ        需要目的地地址。
WSAENETUNREACH                当前无法从本主机联系网络。
WSA_IO_PENDING                成功启动一个重叠操作,过后将有完成指示。

抱歉!评论已关闭.