//以下是一段服务器端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_

|