|
// File: SampleServer.cpp
#include <afx.h>
#include <conio.h>
#include "spserver.h"
#pragma comment(lib,"wsock32.lib")
#define assert ASSERT
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
//----------------------------------------------------------------
// CSPServer Subclass
class CMySPServer: public CSPServer {
typedef CSPServer inherited;
public:
CMySPServer(CSocketIO *s);
protected:
// Required virtual overrides
virtual void Go();
// Other virtual overrides
virtual void SendWelcome();
virtual void Cleanup();
virtual void SendCommandError(const char *cmdline);
//virtual void SessionTrace(const char *szTag, const char *s);
//virtual BOOL CheckAbort();
//virtual BOOL PreprocessLine(char *s);
//virtual BOOL QueryAllowTimeoutDisconnect();
//virtual void OnWaitReceivedDataAbandoned();
//virtual void OnReceiveByteError(const int error);
private:
static TSPDispatch Dispatch[];
BOOL SPD_HELLO(char *args);
BOOL SPD_LOGIN(char *args);
BOOL SPD_SHOW(char *args);
BOOL SPD_HELP(char *args);
BOOL SPD_QUIT(char *args);
CString sClientDomain;
CString sClientIp;
};
//----------------------------------------------------------------
// Dispatch Structure
CSPServer::TSPDispatch CMySPServer::Dispatch[] = {
SPCMD(CMySPServer, "HELLO", SPD_HELLO),
SPCMD(CMySPServer, "LOGIN", SPD_LOGIN),
SPCMD(CMySPServer, "SHOW", SPD_SHOW),
SPCMD(CMySPServer, "HELP", SPD_HELP),
SPCMD(CMySPServer, "QUIT", SPD_QUIT),
{0}
};
//----------------------------------------------------------------
// Constructor
CMySPServer::CMySPServer(CSocketIO *s)
: CSPServer(s, Dispatch)
{
Done = FALSE;
// Get client information (i.e., for logging/filtering)
Control->GetPeerInfo(sClientDomain,sClientIp);
// Start() starts the thread and call Go()
Start();
}
void CMySPServer::SendCommandError(const char *cmdline)
{
Send("!command not understood: %s\r\n",cmdline);
}
BOOL CMySPServer::SPD_HELLO(char *args)
{
Send("--> HELLO(%s)\r\n",args);
return TRUE;
}
BOOL CMySPServer::SPD_LOGIN(char *args)
{
Send("--> LOGIN(%s)\r\n",args);
return TRUE;
}
BOOL CMySPServer::SPD_SHOW(char *args)
{
Send("--> SHOW(%s)\r\n",args);
return TRUE;
}
BOOL CMySPServer::SPD_QUIT(char *)
{
Send("<click> Bye!\r\n");
Control->Shutdown(1);
Done = TRUE;
return TRUE;
}
BOOL CMySPServer::SPD_HELP(char *args)
{
Send("+OK available commands.\r\n");
Send("HELLO\r\n");
Send("LOGIN\r\n");
Send("SHOW\r\n");
Send("HELP\r\n");
Send("QUIT\r\n");
Send(".\r\n");
return TRUE;
}
//----------------------------------------------------------------
// Go() is called by thread handler
void CMySPServer::Go()
{
// By this point, we have a new thread running
printf("tid: %04x Starting Client: %s (%s)\n",GetThreadId(),sClientIp,sClientDomain);
// Go() starts the thread's socket command line
// reader and dispatcher. Go() returns when the
// variable Done is set TRUE or if connection drops.
inherited::Go();
printf("tid: %04x Exiting Client: %s (%s)\n",GetThreadId(),sClientIp,sClientDomain);
// we are done,
delete this;
}
//----------------------------------------------------------------
// SendWelcome() is called by inherited::Go()
void CMySPServer::SendWelcome()
{
Send("Hello! Server ready\r\n");
}
//----------------------------------------------------------------
// Cleanup() is called when the socket has been closed (BY CLIENT)
void CMySPServer::Cleanup()
{
printf("tid: %04x Cleanup Client: %s (%s)\n",GetThreadId(),sClientIp,sClientDomain);
}
//----------------------------------------------------------------
// Socket Listening Thread
class CServerThread : public CThread {
typedef CThread inherited;
public:
CServerThread(const DWORD port = 4044, const DWORD flags = 0);
virtual void Stop();
protected:
virtual void Go();
private:
SOCKET serverSock;
DWORD serverPort;
};
CServerThread::CServerThread(const DWORD port, const DWORD flags)
{
serverSock = INVALID_SOCKET;
serverPort = port;
SetStartFlags(flags);
Start();
}
void CServerThread::Go()
{
printf("* Opening Socket on port: %d\n",serverPort);
serverSock = socket(PF_INET, SOCK_STREAM, 0);
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons((short)serverPort);
sin.sin_addr.s_addr = INADDR_ANY;
if (bind(serverSock, (sockaddr *)&sin, sizeof(sin)) != 0) {
printf("bind error %d\n",GetLastError());
return;
}
if (listen(serverSock, SOMAXCONN) != 0) {
printf("listen error %d\n",GetLastError());
return;
}
printf("* Waiting for connections\n");
while ((serverSock != INVALID_SOCKET) && !IsTerminated()) {
sockaddr_in src;
int x = sizeof(src);
//---------------------------------------------------
// Wait for connection:
//
// Note: Since accept will block the socket handle is
// used as Stop() variable. WinSock will return if
// the socket is set to INVALID_SOCKET. See Stop()
SOCKET t = accept(serverSock, (sockaddr *)&src, &x);
if (serverSock == INVALID_SOCKET) break;
//---------------------------------------------------
if (t == INVALID_SOCKET) continue;
printf("- New Connection!\n");
new CMySPServer(new CSocketIO(t));
} // while
printf("* Exiting Server Thread\n");
}
void CServerThread::Stop()
{
SOCKET s = InterlockedExchange((long *)&serverSock, INVALID_SOCKET);
if (s != INVALID_SOCKET) closesocket(s);
// Note: The thread destructor will also call Stop()
// So this inherited call is redundant
inherited::Stop();
}
//----------------------------------------------------------------
// Main Block
//----------------------------------------------------------------
void main(char argc, char *argv[])
{
WSADATA wd;
if (WSAStartup(MAKEWORD(1, 1), &wd) != 0) {
return;
}
CServerThread server(4044);
printf("* Main Thread Keyboard Wait: Escape to Exit\n");
while (TRUE) {
if (kbhit() && getch() == 27) break;
Sleep(30);
}
printf("* Stopping Server\n");
server.Stop();
printf("* Done. Exiting Main\n");
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.