linux 多路复用 select (二)

linux 多路复用 select (二)_第1张图片


#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib, “ws2_32.lib”)
int main()
{
    // 加载win socket
    WSADATA ws;
    int ret;

    int maxsock; //所要监听的最大套接字描述符

    ret = WSAStartup(MAKEWORD(2, 2), &ws);
    if (ret != 0)
    {
        printf(”WSAStartup() 失败!\n”);
        return -1;
    }
    // 创建侦听SOCKET
    SOCKET sListen;
    sListen = socket(AF_INET, SOCK_STREAM, 0);
    if (sListen == INVALID_SOCKET)
    {
        printf(”socket() 失败!\n”);
        return -1;
    }
    // 填充服务器地址结构
    sockaddr_in servAddr;
    servAddr.sin_family = AF_INET;
    servAddr.sin_addr.s_addr = INADDR_ANY;
    servAddr.sin_port = htons(8000);

    // 绑定服务器套接字
    ret = bind(sListen, (sockaddr*)&servAddr, sizeof(servAddr));
    if (ret == SOCKET_ERROR)
    {
        printf(”bind() 失败!\n”);
        return -1;
    }

    // 开始侦听
    ret = listen(sListen, 5);
    if (ret == SOCKET_ERROR)
    {
        printf(”listen() 失败!\n”);
        return -1;
    }
    printf(”服务器启动成功,在端口%d监听…\n”, ntohs(servAddr.sin_port));
    //使用select模型
    // 创建套接字集合
    fd_set allSockSet; // 总的套接字集合
    fd_set readSet; // 可读套接字集合
    fd_set writeSet; // 可写套接字集合
  

    maxsock= sListen;  

    FD_ZERO(&allSockSet); // 清空套接字集合
    FD_SET(sListen, &allSockSet); // 将sListen套接字加入套接字集合中
    char bufRecv[100]; // 接收缓冲区
    // 进入服务器主循环
    while(1)
    {
        FD_ZERO(&readSet); // 清空可读套接字
        FD_ZERO(&writeSet); // 清空可写套接字
        readSet = allSockSet; // 赋值
        writeSet = allSockSet; // 赋值
        // 调用select函数,timeout设置为NULL
        ret = select(maxsock+1, &readSet, 0, NULL, NULL);
        //
        if (ret == SOCKET_ERROR)
        {
            printf(”select() 失败!\n”);
            return -1;
        }
        // 存在套接字的I/O已经准备好
        if(ret > 0)
        {
            // 遍历所有套接字
            for (int i = 0; i < allSockSet.fd_count; ++i)
            {
                SOCKET s = allSockSet.fd_array[i];
                // 存在可读的套接字
                if (FD_ISSET(s, &readSet))
                {
                    // 可读套接字为sListen
                    if (s == sListen)
                    {
                        // 接收新的连接
                        sockaddr_in clientAddr;
                        int len = sizeof(clientAddr);
                        SOCKET sClient = accept(s, (sockaddr*)&clientAddr, &len);    //这里可以解释上一篇中的客户端的和服务器端的fd(套接字描述符)不同,因为sClient的值是当前系统中没有使用的且最小的数。之前服务器端的fd已经被了使用;
                        // 将新创建的套接字加入到集合中
                        FD_SET(sClient, &allSockSet);
                        printf(”>>>>>有新的连接到来啦…\n”);
                        printf(”目前客户端数目为:%d\n”, allSockSet.fd_count - -);
                    }
                    else // 接收客户端信息
                    {
                        ret = recv(s, bufRecv, 100, 0);
                        // 接收错误
                        if (ret == SOCKET_ERROR)
                        {
                            DWORD err = WSAGetLastError();
                            if (err == WSAECONNRESET)
                            printf(”客户端被强行关闭\n”);
                            else
                            printf(”recv() 失败!”);
                            // 删除套接字
                            FD_CLR(s, &allSockSet);
                            printf(”目前客户端数目为:%d\n”, allSockSet.fd_count - -);
                            break;
                        }
                        if (ret == 0)
                        {
                            printf(”客户端已经退出!\n”);
                            // 删除套接字
                            FD_CLR(s, &allSockSet);
                            printf(”目前客户端数目为:%d\n”, allSockSet.fd_count - -);
                            break;
                        }
                        bufRecv[ret] = ‘\0′;
                        printf(”收到的消息:%s\n”, bufRecv);
                    } // end else

                }// end if

            }// end for 

      for (i = 0; i < allSockSet.fd_count-1; i++){

        if (allSockSet.fd_array[i] < allSockSet.fd_array[i+1] )

               maxsock = allSockSet.fd_array[i+1];     //找出最大的代监视的套接字

     }

        } // end if
    }//end while
    return 0;
}

文章来自:原文

你可能感兴趣的:(linux,select,多路复用)