class CSocketServer
{
private:
SOCKET listenSocket;
static SOCKET acceptSocket;
HANDLE acceptthread;
volatile bool acceptthreadrunnable;
HANDLE shakehandthread;
volatile bool shakehandthreadrunnable;
private:
BYTE srcframeBuf[MAX_FRAME_BUF];
BYTE dstframeBuf[MAX_FRAME_BUF];
int dstframeBufLen;
static unsigned int currentFrameLen ;
static int iState;
static DWORD lastshakehandTime;
private:
CSocketServer(void);
static CSocketServer* instance;
public:
static CSocketServer* GetInstance();
~CSocketServer(void);
bool Start(unsigned int port);
bool Stop();
bool SndMessage(const unsigned char* buf, int buflen);
bool RcvMessage(unsigned char* buf, int buflen, int& rcvlen);
void SetRcvShaveHand();
private:
static DWORD WINAPI acceptThread(LPVOID lpParameter);
static DWORD WINAPI shakeHandThread(LPVOID lpParameter);
public:
void closeSocket(SOCKET& s);
};
CSocketServer::CSocketServer(void)
{
listenSocket = INVALID_SOCKET;
acceptthreadrunnable = false;
acceptthread == NULL;
shakehandthreadrunnable = false;
shakehandthread == NULL;
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR)
{
//printf("Error at WSAStartup()/n");
}
}
CSocketServer::~CSocketServer(void)
{
WSACleanup();
}
void CSocketServer::closeSocket(SOCKET& s)
{
if (s != INVALID_SOCKET && s != SOCKET_ERROR)
{
shutdown(s, SD_BOTH);
closesocket(s);
s = INVALID_SOCKET;
}
}
SOCKET CSocketServer::acceptSocket = INVALID_SOCKET;
unsigned int CSocketServer::currentFrameLen = 0;
int CSocketServer::iState = 1;
DWORD CSocketServer::lastshakehandTime = -1;
CSocketServer* CSocketServer::instance = new CSocketServer();
CSocketServer* CSocketServer::GetInstance()
{
return instance;
}
bool CSocketServer::Start(unsigned int port)
{
WSADATA wsaData;
listenSocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if (listenSocket == INVALID_SOCKET)
{
return false;
}
sockaddr_in saServer;
saServer.sin_family = AF_INET;
saServer.sin_addr.s_addr = htonl(INADDR_ANY);
//saServer.sin_addr.s_addr = inet_addr( "192.168.1.150");
saServer.sin_port = htons(port);
if ( bind( listenSocket, (SOCKADDR*) &saServer, sizeof(saServer) ) == SOCKET_ERROR )
{
return false;
}
if ( listen( listenSocket, 1 ) == SOCKET_ERROR )
{
return false;
}
acceptthreadrunnable = true;
acceptthread = CreateThread(NULL, 0, acceptThread, this, 0, NULL);
lastshakehandTime = -1;
shakehandthreadrunnable = true;
shakehandthread = CreateThread(NULL, 0, shakeHandThread, this, 0, NULL);
if (gbPDACommStatus)
{
WriteDebugInfo("start success/n");
}
return true;
}
DWORD WINAPI CSocketServer::shakeHandThread(LPVOID lpParameter)
{
CSocketServer* server = (CSocketServer*)lpParameter;
while ( server->shakehandthreadrunnable)
{
if (lastshakehandTime != -1 && GetTickCount() - lastshakehandTime > 10*1000)
{
server->closeSocket(acceptSocket);
if (gbPDACommStatus)
{
WriteDebugInfo("disconnect/n");
}
}
Sleep(3000);
}
return 0;
}
DWORD WINAPI CSocketServer::acceptThread(LPVOID lpParameter)
{
CSocketServer* server = (CSocketServer*)lpParameter;
sockaddr_in acceptAddress;
int adressLen;
SOCKET tmpSocket = INVALID_SOCKET;
while ( server->acceptthreadrunnable)
{
adressLen = sizeof(acceptAddress);
tmpSocket = accept( server->listenSocket, (SOCKADDR*) &acceptAddress, &adressLen );
if (acceptSocket == INVALID_SOCKET || acceptSocket == SOCKET_ERROR)
{
if (gbPDACommStatus)
{
WriteDebugInfo("new connect/n");
}
acceptSocket = tmpSocket;
lastshakehandTime = GetTickCount();
currentFrameLen = 0;
iState = 1;
}
else
{
server->closeSocket(tmpSocket);
}
}
return 0;
}
bool CSocketServer::Stop()
{
acceptthreadrunnable = false;
shakehandthreadrunnable = false;
closeSocket(listenSocket);
closeSocket(acceptSocket);
WaitForSingleObject(acceptthread, 5000);
WaitForSingleObject(shakehandthread, 5000);
if (acceptthread != NULL)
{
CloseHandle(acceptthread);
}
if (shakehandthread != NULL)
{
CloseHandle(shakehandthread);
}
if (gbPDACommStatus)
{
WriteDebugInfo("stop server/n");
}
return true;
}
InterLock serverSndLock;
bool CSocketServer::SndMessage(const unsigned char* buf, int buflen)
{
AutoLock<InterLock> autoLock(serverSndLock);
if (acceptSocket == INVALID_SOCKET || acceptSocket == SOCKET_ERROR)
{
return false;
}
int rc = send(acceptSocket, (char*)(buf), buflen, 0);
if(rc == SOCKET_ERROR)
{
if (gbPDACommStatus)
{
WriteDebugInfo("snd error/n");
}
closeSocket(acceptSocket);
return false;
}
if (gbPDACommData)
{
WriteDebugInfo("snd %d/n", buflen);
WriteDebugInfo(buflen, buf);
WriteDebugInfo("/n");
}
return true;
}
InterLock serverRcvLock;
bool CSocketServer::RcvMessage(unsigned char* buf, int buflen, int& rcvlen)
{
AutoLock<InterLock> autoLock(serverRcvLock);
if (acceptSocket == INVALID_SOCKET || acceptSocket == SOCKET_ERROR)
{
return false;
}
fd_set readfds;
struct timeval timeout;
timeout.tv_sec = 1000 / 1000u;
timeout.tv_usec = (1000 % 1000u) * 1000u;
FD_ZERO(&readfds);
FD_SET(acceptSocket, &readfds);
int rc = select(-1, &readfds, NULL, NULL, &timeout);
if (rc == SOCKET_ERROR)
{
if (gbPDACommStatus)
{
WriteDebugInfo("select error/n");
}
closeSocket(acceptSocket);
return false;
}
else if (rc == 0)
{
rcvlen = 0;
return false;
}
rc = recv(acceptSocket, (char*)buf, buflen, 0);
if (rc == SOCKET_ERROR || rc == 0)
{
if (gbPDACommStatus)
{
WriteDebugInfo("recv error/n");
}
closeSocket(acceptSocket);
return false;
}
if (gbPDACommData)
{
WriteDebugInfo("rcv %d/n", rc);
WriteDebugInfo(rc, buf);
WriteDebugInfo("/n");
}
rcvlen = rc;
return true;
}
void CSocketServer::SetRcvShaveHand()
{
lastshakehandTime = GetTickCount();
}