《windows网络编程》第一版的程序里关于Select模型的例子里有这个函数
而第二版里nonblocking的例子,也就是select模型,没有此函数我的程序里,定义了2个UDP socket绑定在同一IP,2个端口上。
如果不用这个ioctlsocket设置socket的话,那么select不能正常运行,程序总是停在select这里。
但是只要用ioctlsocket设置一个socket的话,就可以正常运行了。那么ioctlsocket这个函数在Select模型中是必须的吗?非常感谢!!

解决方案 »

  1.   

    #include "stdafx.h"
    #include "winsock2.h"#define LOCALIP "192.168.3.96"
    #define LOCALPORT 8201
    #define LOCALPORT1 8101#define REMOTEIP "192.168.3.96"
    #define REMOTEPORT 8787
    #define BUFSIZE 1024int main(int argc, char* argv[])
    {
    SOCKET s, s1;
    int Ret;
    WSADATA wsaData;
    SOCKADDR_IN localAddr, remoteAddr, localAddr1;
    int localAddrLen, remoteAddrLen, localAddrLen1;
    fd_set fdRead;
    fd_set fdWright;
    fd_set fdExcept;
    int retSelect;
    char buf[BUFSIZE]; if ((Ret = WSAStartup(0x0202,&wsaData)) != 0)
    {
    printf("WSAStartup() failed with error %d\n", Ret);
    WSACleanup();
    return 1;
    }

    // if ((s = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_IP, NULL, 0, 
    // WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) == INVALID_SOCKET)
    {
    printf("create socket error\n");
    return 1;
    }

    localAddr.sin_addr.s_addr = inet_addr(LOCALIP);
    localAddr.sin_family = AF_INET;
    localAddr.sin_port = htons(LOCALPORT);
    localAddrLen = sizeof(SOCKADDR_IN);

    if (bind(s, (SOCKADDR *)&localAddr, localAddrLen) == SOCKET_ERROR)
    {
    printf("bind error\n");
    return 1;
    } if ((s1 = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) == INVALID_SOCKET)
    {
    printf("create socket error\n");
    return 1;
    }
    localAddr1.sin_addr.s_addr = inet_addr(LOCALIP);
    localAddr1.sin_family = AF_INET;
    localAddr1.sin_port = htons(LOCALPORT1);
    localAddrLen1 = sizeof(SOCKADDR_IN);

    if (bind(s1, (SOCKADDR *)&localAddr1, localAddrLen1) == SOCKET_ERROR)
    {
    printf("bind error\n");
    return 1;
    } ULONG nonBlock = 1;
    // if (ioctlsocket(s, FIONBIO, &nonBlock) == SOCKET_ERROR)
    // {
    // printf("ioctlsocket error\n");
    // return 1;
    // }
    // if (ioctlsocket(s1, FIONBIO, &nonBlock) == SOCKET_ERROR)
    // {
    // printf("ioctlsocket error\n");
    // return 1;
    // } while (1)
    {
    FD_ZERO(&fdRead);
    FD_ZERO(&fdWright);
    FD_ZERO(&fdExcept);
    FD_SET(s, &fdRead);
    FD_SET(s1, &fdRead); printf("selecting¡­¡­\n");
    if (retSelect = select(s + 1, &fdRead, &fdWright, &fdExcept, NULL))
    {
    if (retSelect == SOCKET_ERROR)
    {
    printf("select error\n");
    return 1;
    } if (FD_ISSET(s, &fdRead))
    {
    remoteAddrLen = sizeof(SOCKADDR_IN);
    int nret;
    if ((nret = recvfrom(s, buf, BUFSIZE, 0, (SOCKADDR *)&remoteAddr,
    &remoteAddrLen)) == SOCKET_ERROR)
    {
    printf("recvfrom error\n");
    break;
    }
    else
    {
    buf[nret] = '\0';
    printf("[%s] send msg: %s\n", 
    inet_ntoa(remoteAddr.sin_addr), buf);
    }
    }
    if (FD_ISSET(s1, &fdRead))
    {
    remoteAddrLen = sizeof(SOCKADDR_IN);
    int nret;
    if ((nret = recvfrom(s1, buf, BUFSIZE, 0, (SOCKADDR *)&remoteAddr,
    &remoteAddrLen)) == SOCKET_ERROR)
    {
    printf("recvfrom1 error\n");
    break;
    }
    else
    {
    buf[nret] = '\0';
    printf("[%s] send msg1: %s\n", 
    inet_ntoa(remoteAddr.sin_addr), buf);
    }
    }
    if (FD_ISSET(s, &fdWright))
    {
    printf("fdWright\n");
    }
    if (FD_ISSET(s, &fdExcept))
    {
    printf("fdExcept\n");
    }

    }
    }
    return 0;
    }
      

  2.   

    (ioctlsocket(s, FIONBIO, &nonBlock) 这句话的意思是把S 改成非阻塞模式 
    如果不使用ioctlsocket sock 默认为阻塞模式 
    在使用SELECT的时候要改成 非阻塞模式
      

  3.   

    select会自动把套节字置为非阻塞模式