socket select programing

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

 

#include <stdio.h>

#include <string.h>

#include <WINSOCK2.H>

 

#include <log.h>

#include "socket/HardSocket.h"

#include "socket/LightSocket.h"

#include "SelectEvent.hpp"

 

#define INT_SERVER_PORT 6002

#define STR_SERVER_IP "127.0.0.1"

#define INT_DATABUFFER_SIZE 100

 

class SelectEventBusinessHandler : public SelectEvent 

{

 

public:

 

void onAccept(LightSocket &socket)

{

sockaddr_in addr = socket.getSocketAddress();

debug("handle on accept event from %s:%d(socket %d)", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), socket.getPlainSocket());

}

 

void onMessage(LightSocket &socket, char *bytes)

{

sockaddr_in addr = socket.getSocketAddress();

//打印接收的数据

        info("recv from %s:%d\ndata:%s", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), bytes);

}

};

 

 

class Select : public HardSocket 

{

 

private: 

 

 

fd_set fd;

 

SelectEvent* eventHandler;

 

public:

Select() 

{

Socket::init(AF_INET, SOCK_STREAM, 0);

eventHandler = new SelectEventBusinessHandler();

 

FD_ZERO(&fd);

FD_SET(this->getPlainSocket(), &fd);

}

 

void select()

{

fd_set fdOld = fd;

//timeval tm;

//tm.tv_sec = 0;

//tm.tv_usec = 1000;

        int selected = ::select(0, &fdOld, NULL, NULL, NULL);  

        

if (selected == SOCKET_ERROR)  

        {  

            //WSACleanup();   

//printf("Faild to select sockt in server!/r/n");  

            int error = WSAGetLastError();

warn("select error %d", error);

Sleep(100);  

        }

else if (selected == 0) 

{

warn("select error, time limit expired");

}

else 

        {

            for(int i = 0;i < fd.fd_count; i++) 

            {

SOCKET sfd = fd.fd_array[i];

                if (FD_ISSET(sfd, &fdOld)) 

                {

                    //如果socket是服务器,则接收连接

                    if (sfd == this->getPlainSocket()) 

{

onAccept();

                    }

                    else //非服务器,接收数据(因为fd是读数据集)

                    {

onRead(sfd);

                    }

                }

else 

{

warn("socket fd %d not in fd set", sfd);

}

            }

        }

}

 

void onAccept() 

{

sockaddr_in addrAccept;

        int so_sockaddr_in = sizeof(sockaddr_in);

memset(&addrAccept, 0, so_sockaddr_in);

 

 

        SOCKET sockAccept = ::accept(this->getPlainSocket(), (sockaddr *) &addrAccept, &so_sockaddr_in);  

        if (sockAccept == INVALID_SOCKET) 

        {

   warn("accepted an invalid socket connection");

return;

}

        FD_SET(sockAccept, &fd);

        //FD_SET(sockAccept,&fdOld);

        info("%s:%d has connected server!", inet_ntoa(addrAccept.sin_addr), ntohs(addrAccept.sin_port));

 

LightSocket *cs = new LightSocket(sockAccept);

cs->setSocketAddress(addrAccept);

eventHandler->onAccept(*cs);

}

 

void onRead(SOCKET sfd) 

{

char szDataBuff[INT_DATABUFFER_SIZE];///

        memset(szDataBuff, 0, INT_DATABUFFER_SIZE);

szDataBuff[INT_DATABUFFER_SIZE - 1] = '\0';

 

        int bytes = recv(sfd, szDataBuff, INT_DATABUFFER_SIZE - 1, 0);

        

sockaddr_in addr;

int so_sockaddr_in = sizeof(sockaddr_in);

memset(&addr, 0, so_sockaddr_in);

        getpeername(sfd, (sockaddr *) &addr, &so_sockaddr_in);

        if (bytes == SOCKET_ERROR)  

        {

int error = WSAGetLastError();

            warn("Fail to receive data from %s:%d error %d", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), error);

closesocket(sfd);

            FD_CLR(sfd, &fd);

            //i--;

            return;

        }

 

        if (bytes == 0) 

        {

            //客户socket关闭  

            warn("%s:%d has closed!", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));

 

            closesocket(sfd);

            FD_CLR(sfd, &fd);

            //i--;

        }  

          

        if (bytes > 0) 

        {

LightSocket *cs = new LightSocket(sfd);

cs->setSocketAddress(addr);

eventHandler->onMessage(*cs, szDataBuff);

        }

}

};

 

void main(void)

{

///*

Select *socket = new Select();

 

bool bReuseAddr = true;

socket->setSocketOption(SOL_SOCKET, SO_REUSEADDR, (char *) &bReuseAddr, sizeof(bReuseAddr));

    //unsigned   long cmd = 1;

    //iResult= ioctlsocket(sockServer,FIONBIO,&cmd);

socket->bind(INT_SERVER_PORT);

socket->listen(5);

 

    info("Start server...");

while(1)

{

        socket->select();

    }  

    WSACleanup();

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值