Discussion:
CAsyncSocket implementaion in C++ Console application
(too old to reply)
c***@gmail.com
2013-07-05 13:29:26 UTC
Permalink
I found an interesting solution of that issue.
First of all:
YES its possible to use CAsyncSocket with full features without a CWin Window.
NO its no common Console App.
And it works fine :-)

You need a CWorker Class derived from CWinApp, because CWinApp:CWinThread has the MFC-Message-Loop Run().
class CWorkerApp :public CWinApp;

Second you need your CAsync Class derived from CAsyncSocket, to override the virtual Callbacks.
class CAsync :public CAsyncSocket;

Third you must tell CWinApp tu run without a CWin-Dialog, because default it stops, if it has no Window.
AfxOleSetUserCtrl(FALSE);
Keep in mind, you have no UI to that App. You just see it under Processes in Task-Manager and you can Kill it only that way.
But the good message, you can allocate a Console Window to put your DEBUG output there.
The rest I found in MSDN dokumentation, Sample EchoServer, and "of course" in Internet :))

I post the full source afterwards. They consist of
MyEchoSocket.h
EchoServer.h
MyEchoSocket.cpp
EchoServer.cpp

// MyEchoSocket.h : header file
//

#if !defined(AFX_MYECHOSOCKET_H__166D4120_2F94_4231_AE60_7C719E3EC05C__INCLUDED_)
#define AFX_MYECHOSOCKET_H__166D4120_2F94_4231_AE60_7C719E3EC05C__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class MyEchoSocket : public CAsyncSocket
{
public:
//my Overwrites of the Callbacks of the Socket-Events, I hook on by Create
virtual void OnReceive(int nErrorCode); //FD_READ
virtual void OnSend(int nErrorCode); //FD_WRITE
virtual void OnOutOfBandData(int nErrorCode); //FD_OOB
virtual void OnAccept(int nErrorCode); //FD_ACCEPT
virtual void OnConnect(int nErrorCode); //FD_CONNECT
virtual void OnClose(int nErrorCode); //FD_CLOSE

BOOL Create(
UINT nSocketPort = 0,
int nSocketType = SOCK_STREAM,
long lEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE,
LPCTSTR lpszSocketAddress = NULL
);

void SetParentApp(CWinApp* pParent);

MyEchoSocket();
virtual ~MyEchoSocket();

private:
CWinApp* m_pParent;
};

#endif // !defined(AFX_MYECHOSOCKET_H__166D4120_2F94_4231_AE60_7C719E3EC05C__INCLUDED_)

// EchoServer.h
//

#if !defined(AFX_ECHOSERVER_H__7AA7D190_8407_49A5_A315_FB3E228E6F80__INCLUDED_)
#define AFX_ECHOSERVER_H__7AA7D190_8407_49A5_A315_FB3E228E6F80__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#ifndef __AFXWIN_H__
#error include 'stdafx.h' before including this file for PCH
#endif

#include "resource.h" // main symbols
#include "MyEchoSocket.h"

class CEchoServerApp : public CWinApp
{
public:
void JobOnReceive();
void JobOnClose();
void JobOnAccept();

CEchoServerApp();

int m_port;
CString m_recieveddata;
CString m_status;

virtual BOOL InitInstance();
virtual int ExitInstance( );

//declare the Message-Loop ========================================
DECLARE_MESSAGE_MAP()

private:
MyEchoSocket m_sListener;
MyEchoSocket m_sConnected;
};

#endif // !defined(AFX_ECHOSERVER_H__7AA7D190_8407_49A5_A315_FB3E228E6F80__INCLUDED_)

// MyEchoSocket.cpp
//

#include "stdafx.h"
#include "EchoServer.h"
#include "MyEchoSocket.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

MyEchoSocket::MyEchoSocket()
{}

MyEchoSocket::~MyEchoSocket()
{}

void MyEchoSocket::OnAccept(int nErrorCode)
{
_cprintf_s("==> OnAccept ++++++++++++++\n");
if(nErrorCode==0)
{
reinterpret_cast<CEchoServerApp*>(m_pParent)->JobOnAccept();
}
CAsyncSocket::OnAccept(nErrorCode);
}

void MyEchoSocket::OnClose(int nErrorCode)
{
_cprintf_s("==> OnClose ++++++++++++++\n");
if(nErrorCode==0)
{
reinterpret_cast<CEchoServerApp*>(m_pParent)->JobOnClose();
}
CAsyncSocket::OnClose(nErrorCode);
}

void MyEchoSocket::OnConnect(int nErrorCode)
{
_cprintf_s("==> OnConnect ++++++++++++++\n");
CAsyncSocket::OnConnect(nErrorCode);
}

void MyEchoSocket::OnOutOfBandData(int nErrorCode)
{
CAsyncSocket::OnOutOfBandData(nErrorCode);
}

void MyEchoSocket::OnReceive(int nErrorCode)
{
_cprintf_s("==> OnReceive ++++++++++++++\n");
if(nErrorCode==0)
{
reinterpret_cast<CEchoServerApp*>(m_pParent)->JobOnReceive();
}
CAsyncSocket::OnReceive(nErrorCode);
}

void MyEchoSocket::OnSend(int nErrorCode)
{
_cprintf_s("==> OnSend ++++++++++++++\n");
CAsyncSocket::OnSend(nErrorCode);
}

BOOL MyEchoSocket::Create(UINT nSocketPort, int nSocketType, long lEvent, LPCTSTR lpszSocketAddress)
{
return CAsyncSocket::Create(nSocketPort, nSocketType, lEvent, lpszSocketAddress);
}

void MyEchoSocket::SetParentApp(CWinApp *pParent)
{
m_pParent=pParent;
}

// EchoServer.cpp
//

#include "stdafx.h"
#include "EchoServer.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//default Message-Loop of CWinApp =====================================
BEGIN_MESSAGE_MAP(CEchoServerApp, CWinApp)
END_MESSAGE_MAP()

CEchoServerApp::CEchoServerApp()
{}

CEchoServerApp theApp;

BOOL CEchoServerApp::InitInstance()
{
//I allocate a Console for CWinApp-Output =========================
BOOL R = AllocConsole();
if (!R)
{
AfxMessageBox("No Console");
return FALSE;
}
_cprintf_s("InitInstance()\n");

//prevent CWinApp from stopping without CWnd ======================
AfxOleSetUserCtrl(FALSE);

//initialize Windows Socket =======================================
if(AfxSocketInit()==FALSE)
{
_cprintf_s("Sockets Could Not Be Initialized");
return FALSE;
}

m_sListener.SetParentApp(this);
m_sConnected.SetParentApp(this);
m_port=12345;
// m_port=0; //Listen on all Ports does not work!

//I start the Listener here ==========================================
m_sListener.Create(m_port);
if(m_sListener.Listen()==FALSE)
{
_cprintf_s("Unable to Listen on that port,please try another port");
m_sListener.Close();
return FALSE;
}
_cprintf_s("++>Server is listening...\n");

return TRUE; //to start CWinApp::Run() -the MFC Message Loop- ========
}
int CEchoServerApp::ExitInstance()
{
_cprintf_s("ExitInstance: press ENTER to close App...");
char cb[256];
size_t sRead;
errno_t err = _cgets_s(cb, 255, &sRead);

//Cleanup ============================================================
BOOL R = FreeConsole();
if (!R)
{
//error
return 1;
}
return 0;
}

void CEchoServerApp::JobOnAccept()
{
CString strIP;
UINT port;
if(m_sListener.Accept(m_sConnected))
{
m_sConnected.GetSockName(strIP,port);
m_status="Client Connected,IP :"+ strIP;
_cprintf_s("++>%s Port:%d\n", m_status, port);
}
else
{
_cprintf_s("Can not Accept Connection");
}
}
void CEchoServerApp::JobOnClose()
{
_cprintf_s("++>post WM_QUIT\n");
AfxPostQuitMessage(0); //send WM_QUIT Message
}
void CEchoServerApp::JobOnReceive()
{
char pBuf[1024];
CString strData;
int iLen;
iLen=m_sConnected.Receive(pBuf,1023);
if(iLen==SOCKET_ERROR)
{
_cprintf_s("Could not Recieve");
}
else
{
pBuf[iLen]=NULL;
strData=pBuf;
m_recieveddata.Insert(m_recieveddata.GetLength(),strData); //store in class
_cprintf_s("++>%s\n", strData);
m_sConnected.Send(pBuf,iLen); //echo
//m_sConnected.ShutDown(0);
}

}
c***@gmail.com
2013-07-05 13:35:42 UTC
Permalink
I forgot the Includes of stdafx.h.

// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//

#if !defined(AFX_STDAFX_H__BA0ED324_F513_410F_A554_9CD9FABD7A80__INCLUDED_)
#define AFX_STDAFX_H__BA0ED324_F513_410F_A554_9CD9FABD7A80__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers

#include <conio.h>
#include <afxwin.h> // MFC core and standard components
#include <afxext.h> // MFC extensions
#include <afxdisp.h> // MFC Automation classes
#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h> // MFC support for Windows Common Controls
#endif // _AFX_NO_AFXCMN_SUPPORT
#include "afxsock.h"

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_STDAFX_H__BA0ED324_F513_410F_A554_9CD9FABD7A80__INCLUDED_)
Loading...