//以下是一段服务器端SDK代码, 较简单, 稍加修改可应用于NT服务程序中
//仅供初学者参考, 高手勿入, 谢谢
#pragma warning(disable: 4530)
#pragma warning(disable: 4786)
#include <map>
#include <cassert>
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
#include <exception>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <tchar.h>
#include <ctime>
using namespace std;
#include <winsock2.h>
#include <windows.h>
#include "thread.h"//该文件见本文末
#include "threadpool.h"//见我的WIN32线程池文章
char * GetErrorMessage(char *szBuffer, DWORD dwSize)
{
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
szBuffer,
dwSize - 1,
NULL
);
return szBuffer;
}
class RFC868TCPServer : public ThreadJob, public Thread
{
SOCKET _S37;
long _lWorkCount;
bool _fRunFlag;
u_long _uIP;
ThreadPool _TP;
public:
RFC868TCPServer(DWORD tp_num = 10) : _TP(tp_num), _S37(INVALID_SOCKET), _lWorkCount(0), _fRunFlag(true)
{
_uIP = htonl(INADDR_ANY); //默认监听IP为本地
}
~RFC868TCPServer()
{
if(_S37 != INVALID_SOCKET)
closesocket(_S37);
}
bool Begin()//开始监听并启动线程
{
char Buffer[256];
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(37);
server.sin_addr.s_addr = _uIP;
if((_S37 = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
return false;
unsigned long NonBlock = 1;
if(ioctlsocket(_S37, FIONBIO, &NonBlock) == SOCKET_ERROR)
return false;
if(bind(_S37, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
return false;
if(listen(_S37, 20) == SOCKET_ERROR)
return false;
return Thread::Begin();
}
inline bool End()
{
_fRunFlag = false;
Sleep(100);
return Thread::End();
}
inline bool WaitEnd(DWORD dwWaitTime = INFINITE)
{
_fRunFlag = false;
return !Wait(dwWaitTime) ? Thread::End() : true;
}
virtual void DoJob(void *para)//线程池的作业
{
SOCKET s = *(SOCKET *)para;
delete para;
time_t cur_time = time(NULL) + 2208988800;
char s_buf[4], *tp = ((char *)&cur_time) + 3;
for(int i=0; i<4; i++)
s_buf[i] = *tp--;
if(send(s, s_buf, 4, 0) == SOCKET_ERROR)
{
LogError();
closesocket(s);
return;
}
if(shutdown(s, SD_SEND) == SOCKET_ERROR)
{
LogError();
closesocket(s);
return;
}
closesocket(s);
InterlockedIncrement(&_lWorkCount);
}
inline void LogMessage(char *szStr)
{
Thread::Lock();
cout << szStr << endl;
Thread::UnLock();
}
inline void LogError()
{
char Buffer[256];
LogMessage(GetErrorMessage(Buffer, 256));
}
inline long GetWorkCount()
{
return _lWorkCount;
}
inline void SetIP(char *szIPStr)
{
_uIP = inet_addr(szIPStr);
}
inline void SetIP(u_long ip)
{
_uIP = ip;
}
virtual void WorkProc()
{
char Buffer[500];
SOCKET ns, s = _S37;
struct sockaddr_in client;
int len = sizeof(client), ret;
FD_SET read_set;
timeval tv = {0, 100000}; //tv.tv_sec = 0, tv.tv_usec = 100000;
while(_fRunFlag)
{
FD_ZERO(&read_set);
FD_SET(s, &read_set);
ret = select(0, &read_set, NULL, NULL, &tv);//Selet模型
if(ret == SOCKET_ERROR)
{
LogMessage(GetErrorMessage(Buffer, 500));
continue;
}
if(FD_ISSET(s, &read_set))//等到客户端
{
ns = accept(s, (struct sockaddr *)&client, &len);
if(ns != INVALID_SOCKET)
{
_TP.Call(this, new SOCKET(ns));//调用线程池
sprintf(Buffer, "Accept Client %s (%d)\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
LogMessage(Buffer);
}
else
LogMessage(GetErrorMessage(Buffer, 500));
}
}
_TP.EndAndWait();
}
};
int main(int argc, char *argv[])
{
try
{
char Buffer[256];
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2, 2);
if(WSAStartup(wVersionRequested, &wsaData))
{
cout << __LINE__ << GetErrorMessage(Buffer, 256) << endl;
return 1;
}
RFC868TCPServer tcp;
if(!tcp.Begin())
cout << __LINE__ << GetErrorMessage(Buffer, 256) << endl;
for(;;)
{
Sleep(200);
if(tcp.GetWorkCount() >= 5)//完成5客户端的时间发送就退出
break;
}
tcp.WaitEnd();
WSACleanup();
}
catch(exception &e)
{
cout << e.what() << endl;
}
return 0;
}
//------------------------------------------thread.h-------------------------------------------------
#ifndef _THREAD_H_
#define _THREAD_H_
#include <assert.h>
#include <windows.h>
class Thread
{
typedef DWORD WINAPI ThreadProcType(LPVOID lpPara);
static DWORD WINAPI DefaultThreadProc(LPVOID lpPara)
{
Thread *pThis = (Thread *)lpPara;
pThis->WorkProc();
return 0;
}
CRITICAL_SECTION _csBaseThreadLock;
protected:
virtual void WorkProc()
{
}
HANDLE _hThreadHandle;
DWORD _dwThreadID;
public:
Thread()
{
_hThreadHandle = NULL;
InitializeCriticalSection(&_csBaseThreadLock);
}
~Thread()
{
DeleteCriticalSection(&_csBaseThreadLock);
if(!_hThreadHandle)
CloseHandle(_hThreadHandle);
}
Thread(Thread&)
{
_hThreadHandle = NULL;
}
Thread& operator =(Thread& x)
{
return *this;
}
bool IsRunning()
{
return _hThreadHandle != NULL;
}
void Lock()
{
EnterCriticalSection(&_csBaseThreadLock);
}
void UnLock()
{
LeaveCriticalSection(&_csBaseThreadLock);
}
inline bool Begin(ThreadProcType ThreadProc = DefaultThreadProc)
{
if(!IsRunning())
_hThreadHandle = CreateThread(NULL, 0, ThreadProc, this, 0, &_dwThreadID);
return IsRunning();
};
inline bool Begin(ThreadProcType ThreadProc , LPVOID lpPara)
{
if(!IsRunning())
_hThreadHandle = CreateThread(NULL, 0, ThreadProc, lpPara, 0, &_dwThreadID);
return IsRunning();
};
inline bool End(DWORD dwEndCode = 0)
{
if(IsRunning())
{
if(!TerminateThread(_hThreadHandle, dwEndCode))
return false;
else
{
CloseHandle(_hThreadHandle);
_hThreadHandle = NULL;
return true;
}
}
return false;
}
inline virtual bool Wait(DWORD dwWaitTime = INFINITE)
{
return IsRunning() ? WaitForSingleObject(_hThreadHandle, dwWaitTime) == WAIT_OBJECT_0 : false;
}
inline bool Suspend()
{
return IsRunning() ? SuspendThread(_hThreadHandle) != 0xFFFFFFFF : false;
}
inline bool Resume()
{
return IsRunning() ? ResumeThread(_hThreadHandle) != 0xFFFFFFFF : false;
}
inline int GetPriority()
{
assert(IsRunning());
return GetThreadPriority(_hThreadHandle);
}
inline bool SetPriority(int iPriority)
{
assert(IsRunning());
return SetThreadPriority(_hThreadHandle, iPriority);
}
inline const HANDLE GetThreadHandle()
{
return _hThreadHandle;
}
inline const DWORD GetThreadID()
{
return _dwThreadID;
}
} ;
#endif //_THREAD_H_