typedef struct _SocketState // socket state & control
{
   char operation;
   SOCKET socket;
   DWORD length;
   char buf[MAX_BUF];
} SocketState;static SocketState* new_socket_state(void)
{
    return (SocketState *)calloc (1, sizeof(SocketState));
}static WSAOVERLAPPED* new_overlapped(void)
{
      return (WSAOVERLAPPED *)calloc (1, sizeof(WSAOVERLAPPED));
} newSocketState = new_socket_state();
 newSocketState->socket = socketState->socket;//此处的socketState->socket是已经建立连接的socket;CreateIoCompletionPort((HANDLE)newSocketState->socket, cpl_port,(ULONG_PTR)newSocketState, 0) //绑定到完成端口上;
==================
我要投递两个io:
socketState->operation = OP_READ;
WSARecv(newSocketState ->socket, &wsabuf, 1, NULL, &flags, ovl, NULL)
socketState->operation = OP_WRITE;
WSASend(newSocketState ->socket, &wsabuf, 1, NULL, 0, ovl, NULL)
这里我不可能让socketState->operation同时为OP_READ或者OP_WRITE两个值吧?这里应该如何处理?

解决方案 »

  1.   

    用 WSAEventSelect(s, hEventObject, FD_READ|FD_WRITE|FD_CLOSE); 事件驱动可以么, 然后用 WSAEnumNetworkEvents 检查
      

  2.   

    IOCP还要用事件选择,没有其它方式吗?
      

  3.   

    我的意思是这样的,先投递:
    socketState->operation = OP_READ;
    WSARecv(newSocketState ->socket, &wsabuf, 1, NULL, &flags, ovl, NULL)
    这个时候GetQueuedCompletionStatus还没有返回,也就是WSARecv还没有完成 ,紧接着投递
    socketState->operation = OP_WRITE;
    WSASend(newSocketState ->socket, &wsabuf, 1, NULL, 0, ovl, NULL)
    这样一来socketState->operation = OP_WRITE就覆盖了socketState->operation = OP_READ,然后
    GetQueuedCompletionStatus返回来的操作只能socketState->operation = OP_WRITE,而不会得到socketState->operation = OP_READ。这个怎么解决?
      

  4.   

    IOCP二:同时发送和接收
      

  5.   

    关键是绑定的key是相同的newSocketState。
      

  6.   

    先后几乎同时投递WSARecv和WSASend,投递WSARecv时,设置newSocketState ->operation = OP_READ; 紧接着投递WSASend时,设置newSocketState ->operation = OP_WRITE;
    当GetQueuedCompletionStatus返回两次(WSARecv和WSASend)后,程序都会进入OP_READ分支处理。 
      

  7.   

    8楼分析的有道理
    投递是依赖于业务的,并不是连接后就直接投递读和写
    server是被动响应的,
    需要接收数据才会发出读投递;
    如果需要发送数据,才会进行写投递。
      

  8.   

    逻辑先不论,如果要投递两个请求,使用两个newSocketState 就可以了
      

  9.   

    你可以同时投递Send和Recv,绑定2个WSBuf,在投递期间保持绑定的buffer有效。
      

  10.   

    IOCP用起来可以说是最方便的框架了。完全不必搞得这么麻烦。事件驱动你可以这么写:iocp事件的定义:
    struct iocp_evt;/* iocp事件处理函数 */
    typedef void (*iocp_evt_handler)(void *priv, struct iocp_evt *evt);/* 定义iocp事件,将overlapped与事件绑定起来 */
    struct iocp_evt {
        iocp_evt_handler handler;
        void *priv;
        OVERLAPPED overlapped;
        DOWRD numberOfBytes;
        DOWRD dwError;
        ULONG_PTR key;
    }
    /* 事件初始化 */
    void iocp_evt_init(struct iocp_evt *evt, iocp_evt_handler handler, void *priv)
    {
        evt->handler = handler;
        evt->priv = priv;
        memset(&evt->overlapped, 0, sizeof(OVARLAPPED));
    }事件被触发时的处理函数:
    void on_wsa_recv(void *priv, struct iocp_evt *evt)
    {
        /* 拿到IOCP中的错误码 */
        DOWRD dwError = evt->dwError;    /* 拿到IOCP传输的字节数 */
        DOWRD numberOfBytes = evt->numberOfBytes;    /* 拿到IOCP绑定时的Key */
        ULONG_PTR key = evt->key;    /* 拿到自己携带的上下文 */
        void *context = priv;    /* ... */
    }
    投递IOCP事件处的写法:/* 生成iocp事件 */
    struct iocp_evt *evt = (struct iocp_evt *)malloc(sizeof(struct iocp_evt));
    /* 传入事件回调函数和自己的上下文指针对事件进行初始化 */
    iocp_evt_init(evt, on_wsa_recv, user_data);/* 投递时,将IOCP事件中的overlapped成员传入 */
    WSARecv(socket, &wsabuf, 1, NULL, &flags, &evt->overlapped, NULL);
    GetQueuedCompletionStatus处的写法:while (1)
    {
        DWORD numberOfBytes;
        ULONG_PTR key;
        LPOVERLAPPED *pOverlapped;
        struct iocp_evt *iocp_evt;    DWORD dwError = GetQueuedCompletionStatus(iocp_handle, &numberOfBytes, &key, &pOverlapped, INFINITE) ? 0 : GetLastError();    /* 若pOverlapped不为零,则有一个iocp事件被完成 */
        if (pOverlapped != NULL)
        {
              /* 通过struct iocp_evt的overlapped成员指针拿到iocp_evt指针 */
              iocp_evt = CONTAINING_RECORD(pOverlapped, struct iocp_evt, overlapped);          /* 设置此次IOCP事件的处理结果 */
              iocp_evt->dwError = dwError;
              iocp_evt->key = key;
              iocp_evt->numberOfBytes = numberOfBytes;          /* 处理事件 */
              iocp_evt->handler(iocp_evt->priv, iocp_evt);
         }
    };
      

  11.   

    一个支持上万高并发的简单HTTP服务器写法:
    https://github.com/xiaoliang314/libatask/blob/master/httpserver_win/httpserver.c