#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();
}