Socket 网络模型之Select篇

C++代码

// write by larry  

// 2009-8-20   

// This is server using select model.  

#include "stdafx.h"  

#include <winsock.h>  

#include <stdio.h>  

#define PORT  5150  

#define MSGSIZE  1024  

#pragma comment(lib, "ws2_32.lib")  

int g_iTotalConn = 0;   

SOCKET g_CliSocketArr[FD_SETSIZE];  

DWORD WINAPI WorkerThread(LPVOID lpParam);  

int main(int argc, char* argv[])   

{   

    WSADATA wsaData;  

    SOCKET sListen, sClient;  

    SOCKADDR_IN local, client;  

    int iAddrSize = sizeof(SOCKADDR_IN);   

    DWORD dwThreadId;   

    // Initialize windows socket library   

    WSAStartup(0x0202, &wsaData);  

    // Create listening socket   

    sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  

    // Bind   

    local.sin_family = AF_INET;  

    local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);  

    local.sin_port = htons(PORT);  

    bind(sListen, (sockaddr*)&local, sizeof(SOCKADDR_IN));   

    // Listen   

    listen(sListen, 3);  

    // Create worker thread   

    CreateThread(NULL, 0, WorkerThread, NULL, 0, &dwThreadId);  

    while (TRUE)    

    {   

        // Accept a connection   

        sClient = accept(sListen, (sockaddr*)&client, &iAddrSize);  

        printf("Accepted client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));  

        // Add socket to g_CliSocketArr   

        g_CliSocketArr[g_iTotalConn++] = sClient;  

    }   

    return 0;   

}   

DWORD WINAPI WorkerThread(LPVOID lpParam)  

{   

    int i;   

    fd_set fdread;  

    int ret;   

    struct timeval tv = {1, 0};  

    char szMessage[MSGSIZE];   

    while (TRUE)    

    {   

        FD_ZERO(&fdread);  

        for (i = 0; i < g_iTotalConn; i++)   

        {  

            FD_SET(g_CliSocketArr[i], &fdread);  

        }  

        // We only care read event   

        ret = select(0, &fdread, NULL, NULL, &tv);  

        if (ret == 0)    

        {  

            // Time expired   

            continue;   

        }  

        for (i = 0; i < g_iTotalConn; i++)   

        {  

            if (FD_ISSET(g_CliSocketArr[i], &fdread))   

            {  

                // A read event happened on g_CliSocketArr  

                ret = recv(g_CliSocketArr[i], szMessage, MSGSIZE, 0);  

                if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))   

                {  

                    // Client socket closed   

                    printf("Client socket %d closed.\n", g_CliSocketArr[i]);  

                    closesocket(g_CliSocketArr[i]);  

                    if (i < g_iTotalConn-1)   

                    {  

                        g_CliSocketArr[i--] = g_CliSocketArr[--g_iTotalConn];  

                    }  

                }   

                else    

                {  

                    // We reveived a message from client  

                    szMessage[ret] = '\0';   

                    send(g_CliSocketArr[i], szMessage, strlen(szMessage), 0);  

                }  

            }  

        }  

    }   

}  

// writeby larry

//2009-8-20

// Thisis server using select model.

#include"stdafx.h"

#include<winsock.h>

#include<stdio.h>

#definePORT  5150

#defineMSGSIZE  1024

#pragmacomment(lib, "ws2_32.lib")

intg_iTotalConn = 0;

SOCKETg_CliSocketArr[FD_SETSIZE];

DWORDWINAPI WorkerThread(LPVOID lpParam);

intmain(int argc, char* argv[])

{

   WSADATA wsaData;

   SOCKET sListen, sClient;

   SOCKADDR_IN local, client;

   int iAddrSize = sizeof(SOCKADDR_IN);

   DWORD dwThreadId;

   // Initialize windows socket library

   WSAStartup(0x0202, &wsaData);

   // Create listening socket

   sListen = socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);

   // Bind

   local.sin_family = AF_INET;

   local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

   local.sin_port = htons(PORT);

   bind(sListen, (sockaddr*)&local,sizeof(SOCKADDR_IN));

   // Listen

   listen(sListen, 3);

   // Create worker thread

   CreateThread(NULL, 0, WorkerThread, NULL, 0,&dwThreadId);

   while (TRUE)

   {

      // Accept a connection

      sClient = accept(sListen,(sockaddr*)&client, &iAddrSize);

      printf("Acceptedclient:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));

      // Add socket to g_CliSocketArr

      g_CliSocketArr[g_iTotalConn++] = sClient;

   }

   return 0;

}

DWORDWINAPI WorkerThread(LPVOID lpParam)

{

   int i;

   fd_set fdread;

   int ret;

   struct timeval tv = {1, 0};

   char szMessage[MSGSIZE];

   while (TRUE)

   {

      FD_ZERO(&fdread);

      for (i = 0; i < g_iTotalConn; i++)

      {

         FD_SET(g_CliSocketArr[i], &fdread);

      }

      // We only care read event

      ret = select(0, &fdread, NULL, NULL,&tv);

      if (ret == 0)

      {

         // Time expired

         continue;

      }

      for (i = 0; i < g_iTotalConn; i++)

      {

         if (FD_ISSET(g_CliSocketArr[i],&fdread))

         {

            // A read event happened ong_CliSocketArr

            ret = recv(g_CliSocketArr[i],szMessage, MSGSIZE, 0);

            if (ret == 0 || (ret == SOCKET_ERROR&& WSAGetLastError() == WSAECONNRESET))

            {

               // Client socket closed

               printf("Client socket %dclosed.\n", g_CliSocketArr[i]);

               closesocket(g_CliSocketArr[i]);

               if (i < g_iTotalConn-1)

               {

                  g_CliSocketArr[i--] =g_CliSocketArr[--g_iTotalConn];

               }

            }

            else

            {

               // We reveived a message fromclient

               szMessage[ret] = '\0';

               send(g_CliSocketArr[i],szMessage, strlen(szMessage), 0);

            }

         }

      }

   }

}


这是异步模型中最简单的一种,服务器端的几个主要流程如下:

1.创建监听套接字,绑定,监听;
2.创建工作者线程;
3.创建一个套接字数组,用来存放当前所有活动的客户端套接字,每accept一个连接就更新一次数组;
4.接受客户端的连接。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值