16.3.4 无连接套接字编程(www.cppentry.com)
无连接套接字,也称为数据报,是实现绑定到无连接协议的套接字,使用WSPConnect()函数建立一个到默认目的地址的连接,从而使得套接字可以使用WSPSend()函数和WSPRecv()函数执行面向连接的发送和接收操作。系统会自动丢弃从一个地址而不是指定目的地址接收到的数据报。如UDP和IPX都是基于无连接的协议。
再次调用WSPConnect()函数,即可以修改默认的目的地址,即使套接字已经"连接上"了。此时,接收到的数据报只要与新指定的目的地址不相同,系统即会丢弃数据报的内容。如果使用WSPConnect()函数指定的地址是NULL,则套接字会处于非连接状态,默认的远程地址是不定的,此时WSPSend()函数和WSPRecv()函数会执行失败,并返回WSAENOTCONN,表示当前没有处于连接状态的套接字,但是使用WSPSendTo()函数和WSPRecvFrom()函数可以执行数据发送和数据接收。
WSPSendTo()函数使用异步方式发送数据到指定地址,即发送数据的套接字已经使用WSPConnect()函数建立到指定地址的连接。其函数原型为:
- int WSPSendTo ( SOCKET s, // 表示发送数据
的socket句柄 - LPWSABUF lpBuffers, // 指向WSABUF
结构的数组的指针 - DWORD dwBufferCount, // 指定
lpBuffers数组中的WSABUF结构的个数 - LPDWORD lpNumberOfBytesSent, // 返回此函数发送的数据个数
- DWORD dwFlags, // 指定发送函数的选项
- const struct sockaddr FAR * lpTo,
- // 可选参数,表示指向目的套接字的地址的指针
- int iTolen, // 指定lpTo参数中地址的大小
- LPWSAOVERLAPPED lpOverlapped, // 指向
WSAOVERLAPPED结构的指针 - // 指向发送操作执行完毕后执行的处理函数的指针
- LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
- // 指向WSATHREADID结构的指针,由提供程序在后
续的WPUQueueApc调用中使用 - LPWSATHREADID lpThreadId,
- LPINT lpErrno ); // 指向返回错误代码的指针
因为此函数可以实现异步发送,因此有时需要指定发送完成时执行的处理代码,此时就需要使用lpCompletionRoutine参数指定回调函数,回调函数的原型为:- void CALLBACK CompletionRoutine ( IN DWORD dwError,
- // 指定异步操作的完成状态
- IN DWORD cbTransferred, // 指定发送成功的字节数
- IN LPWSAOVERLAPPED lpOverlapped, // 异步参数
- IN DWORD dwFlags ); // 预留
其中CompletionRoutine是自定义的函数名的占位符,该函数没有返回值。用户可以在此回调函数中执行操作。
使用WSPRecvFrom()函数可以从无连接套接字处接收数据报,并存储源地址。其函数原型为:
- int WSPRecvFrom ( SOCKET s, // 表示接收数
据的socket句柄 - LPWSABUF lpBuffers, // 指向WSABUF
结构的数组的指针 - DWORD dwBufferCount, // 指
定lpBuffers数组中的WSABUF结构的个数 - LPDWORD lpNumberOfBytesRecvd, // 返回此函数接收数据的个数
- LPDWORD lpFlags, // 指定并返回接收函数的选项
- struct sockaddr FAR * lpFrom, // 可选参数,
表示指向源套接字的地址的指针 - LPINT lpFromlen, // 指定lpFrom参数中地址的大小
- LPWSAOVERLAPPED lpOverlapped, // 指向
WSAOVERLAPPED结构的指针 - // 指向接收操作执行完毕后执行的处理函数的指针
- LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
- LPWSATHREADID lpThreadId, // 指向WSATHREADID结构的指针
- LPINT lpErrno ); // 指向返回错误代码的指针
无连接套接字编程(www.cppentry.com)比面向连接套接字的编程(www.cppentry.com)要简单些,因为不需要维护链路、处理错误重发机制等工作。使用WSPSendTo()函数和WSPRecvFrom()函数即可完成无连接套接字的数据的发送和接收,但是因为没有重发机制,所以对于数据传输准确率要求较高的程序是不适合使用无连接套接字编程(www.cppentry.com)。