WinsockI/O模型之重叠I/O模型

来源:互联网 发布:网络抽奖合法吗 编辑:程序博客网 时间:2024/06/09 04:09

重叠I/O很多套接口I/O操作函数.
Winsock2提供了一组以WSA起头函数,WSARecv/WSASend和WSARecvfrom/WSASendto.

几个数据结果:

1)typedef struct _WSABUF{
       u_long len;       // 缓冲区大小.
       char FAR *buf; // 缓冲区指针.
   } WSABUF, FAR *LPWSABUF;

2)typedef struct _WSAOVERLAPPED{
        DWORD Internal;
        DWORD InternalHigh;
        DWORD Offset;
        DWORD OffsetHigh;
        WSAEVENT hEvent;
} WSAOVERLAPPED, *LPWSAOVERLAPPED;

WSAOVERLAPPED是OVERLAPPED结构移植来的,重叠I/O操作初始投递I/O之间进行联系的机制.
前四个参数,由系统内部使用.hEvent设置特定的WSAEVENT对象即可.

3)typedef void(CALLBACK * LPWSAOVERLAPPED_COMPLETION_ROUTINE{
         DWORD dwError,               // 重叠操作的完成状态;
         DWORD cbTransferred,     // 传输字节数
         LPWSAOVERLAPPED   lpOverlapped,   //调用I/O操作时WSAOVERLAPPED结构信息:
         DWORD dwFlags
};-
是Winsock2中重叠I/O回调函数指针,操作完成时自动调用该指针所指向完成函数.
参数分两种情况,对于WSARecv/WSARecvfrom函数接收操作能立即结束
那么dwFlags包含了调用接收函数时的lpFlags参数的信息,对于WSARend/WSASendto来说该参数暂时使用,系统设置为0.
下面列出了四个Winsock2中的重叠I/O操作函数的定义:
      (1)、 int WSARecv(
              SOCKET s,
              LPWSABUP lpBuffers,
              DWORD dwBufferCount,
              LPDWORD lpNumberOfBytesRecvd,
              LPDWORD lpFlags,
              LPWSAOVERLAPPED lpOverlapped,
              LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
        );
      (2)、int WSASend(
              SOCKET s,
              LPWSABUF lpBuffers,
              DWORD dwBufferCount,
              LPDWORD lpNumberOfBytesSent,
              DWORD dwFlags,
              LPWSAOVERLAPPED lpOverlapped,
              LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
        );   
      (3)、int WSARecvFrom(
              SOCKET s,
              LPWSABUF lpBuffers,
              DWORD dwBufferCount,
              LPDWORD lpNumberOfBytesRecvd,
              DWORD dwFlags,
              struct sockaddr FAR *lpFrom,
              LPWSAOVERLAPPED lpOverlapped,
              LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
        );   
      (4)、int WSASendTo(
              SOCKET s,
              LPWSABUF lpBuffers,
              DWORD dwBufferCount,
              LPDWORD lpNumberOfBytesSent,
              DWORD dwFlags,
              struct sockaddr FAR *lpTo,
              int iToLen,
              LPWSAOVERLAPPED lpOverlapped,
              LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
        );  
   套接口s必须重叠套接口.直接调用socket函数或以参数dwFlags为WSA_FLAG_OVERLAPPED参数调用WSASocket.
   下面两行代码完成同样套接口创建工作.(代码略)
   sock = WSASocket(AF_INEF, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
   sock = socket(AF_INET, SOCK_STREAM, 0);
   按照 lpOverlapped 和 lpCompletionRoutine3种不同工作状态:
   1).两种均设为NULL非重叠I/O操作处理,发送,接收函数.
   2).lpCompletionRoutine为NULL,调用这些I/O函数时lpOverlapped构中hEvent事件会被自动复位为未触发,重叠I/O操作完成被设置为已触发WSAWaitForMultipleEvents或者WSAGetOverlappedResult等待或论询该事件对象的状态.
   3).lpCompletionRoutine不为NULL,那么hEvent参数将被忽略,完成例程传递信息.
   调用WSAGetOverlappedResult应注意fWait参数不能设置为TRUE 重叠数据发送/接收将工作非阻塞模式,函数调用能立即返回
    1.返回0 已立即完成并且无错误发生.
    2.返回SOCKET_ERROR,错误码为997(WSA_IO_PENDING),重叠I/O操作已成功初始化,完成后应用进程会得到系统通知.
    3.返回SOCKET_ERROR,错误码不是WSA_IO_PENDING重叠I/O操作初始化失败.
    调用WSAGetOverlappedResult函数来获取指定套接口的最近一次重叠操作结构.
   
    BOOL WSAGetOverlappedResult(
                SOCKET s,
                LPWSAOVERLAPPED lpOverlapped,
                LPDWORD lpcbTransfer,
                BOOL fWait,LPDWORD lpdwFlags
    );
    lpdwFlags,lpcbTransfer输出参数外,余均匀输入参数.
    其中s是感兴趣的套接口描述字,lpOverlapped用于返回在该套接口的最近一次重叠操作时的WSAOverlapped结构数据,
    lpcbTransfer输出重叠操作传输字节数,lpdwFlags用于输出操作的参数,fWait参数是否要等待事件对象lpOverlapped->hEvnet,
    才能将fWait设置为TRUE.如果无错误发生,返回TRUE,说明重叠操作已成功完成;否则返回FALSE,
    重叠操作没有完成,重叠操作已完成但发生了错误,参数设置错误导致重叠操作的状态无法判断.

http://szzhliu.blog.163.com/blog/static/35130895201072111211726/

原创粉丝点击