Click here to Skip to main content
11,635,142 members (77,824 online)
Click here to Skip to main content
Add your own
alternative version

Use of free SocketPro package for creating super client and server applications

, 23 Feb 2002 141K 5.9K 59
A set of socket libraries for writing distributed computing applications over the internet
socketpro.zip
netdemo
ClientComponents
MultiSvsSample
SvrComponents
bin
include
lib
Samples
client
DnsSvs
GetHTML
InternetIO
MultiSvsSample
SpeedTest
res
DResolver
Svr
NormalApp
NTSvs
help
trash
SecureSocket
SafeSocket
DNSResolver.exe
GetHtml.exe
IONet.exe
MultipleSvs.exe
MultiSvs.exe
MultiSvsClient.exe
NetBaseR.dll
SafeSocket.exe
SecureSocket.exe
SpeedTest.exe
ClientSocket.dll
DResolver.dll
SBroker.dll
SockFile.dll
fundamental.gif
patterns.gif
NetBaseR.lib
DNSResolver
DNSResolver.vbp
DNSResolver.vbw
frmDNSResolver.frm
frmDNSResolver.frx
frmChatClient.frm
frmChatClient.frx
GETHTML.vbp
GETHTML.vbw
iIO.frm
IONet
IONet.vbp
IONet.vbw
frmMultiSvs.frm
frmMultiSvs.frx
MultiSvs.vbp
MultiSvs.vbw
SafeSocket.vbp
SafeSocket.vbw
SecureSocket.frm
SpeedTest.ico
SpeedTest.aps
SpeedTest.clw
SpeedTest.dsp
SpeedTest.dsw
dlldata.obj
DNS.rgs
DResolver.aps
DResolver.def
DResolver.dsp
DResolver.dsw
DResolver.opt
DResolver.plg
DResolver.tlb
DResolverps.def
DResolverps.exp
DResolverps.lib
DResolverps.mk
DResolver_i.obj
DResolver_p.obj
MultipleSvs.dsp
MultipleSvs.dsw
MultiSvs.dsp
MultiSvs.dsw
MultiSvs.rgs
MultiSvs.tlb
MultiSvsps.def
MultiSvsps.mk
dlldata.obj
SafeSocket.aps
SafeSocket.dsp
SafeSocket.dsw
SafeSocket.plg
SafeSocket.rgs
SafeSocket.tlb
SafeSocketps.def
SafeSocketps.dll
SafeSocketps.exp
SafeSocketps.lib
SafeSocketps.mk
SafeSocket_i.obj
SafeSocket_p.obj
SPassword.rgs
MultipleSvs.exe
MultiSvs.exe
NetBaseR.dll
SafeSocket.exe
// SpeedTestDlg.cpp : implementation file
//

#include "stdafx.h"
#include "SpeedTest.h"
#include "SpeedTestDlg.h"

#include <SockUtil.h>
#include <atlbase.h>
#include "..\..\Svr\HostDnsSvs.h"

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

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSpeedTestDlg dialog

CSpeedTestDlg::CSpeedTestDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CSpeedTestDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CSpeedTestDlg)
	m_strClients = _T("");
	m_strHost = _T("");
	m_nPort = 1739;
	m_dwTime = 0;
	m_nBytes = 0;
	m_nNagleTime = 0;
	m_bNagle = FALSE;
	m_nRepeat = 100;
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CSpeedTestDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CSpeedTestDlg)
	DDX_Text(pDX, IDC_HOST_EDIT, m_strHost);
	DDX_Text(pDX, IDC_PORT_EDIT, m_nPort);
	DDX_Text(pDX, IDC_TIMECOST_EDIT, m_dwTime);
	DDX_Text(pDX, IDC_BYTES_EDIT, m_nBytes);
	DDX_Text(pDX, IDC_NAGLETIME_EDIT, m_nNagleTime);
	DDX_Check(pDX, IDC_NAGLE_CHECK, m_bNagle);
	DDX_Text(pDX, IDC_REPEAT_EDIT, m_nRepeat);
	DDV_MinMaxUInt(pDX, m_nRepeat, 1, 8000);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CSpeedTestDlg, CDialog)
	//{{AFX_MSG_MAP(CSpeedTestDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_CONNECT_BUTTON, OnConnectButton)
	ON_BN_CLICKED(IDC_DISCONNECT_BUTTON, OnDisconnectButton)
	ON_BN_CLICKED(IDC_ASYN_NAGLE_BUTTON, OnAsynNagleButton)
	ON_BN_CLICKED(IDC_ASYN_BATCH_BUTTON, OnAsynBatchButton)
	ON_BN_CLICKED(IDC_SYN_ONE_BUTTON, OnSynOneButton)
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_NAGLE_CHECK, OnNagleCheck)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSpeedTestDlg message handlers

BOOL CSpeedTestDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CSpeedTestDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CSpeedTestDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CSpeedTestDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

bool CSpeedTestDlg::Run()
{
	DWORD	dwBytes=0;

	//make sure if any data is available
	if(!IOCtl(FIONREAD, dwBytes)||dwBytes<sizeof(CStreamHeader))
		return false;
	
	BYTE	*pBuffer=new BYTE[dwBytes];
	m_nBytes +=RecvBigChunk(pBuffer, dwBytes);
	m_dwTime=::GetTickCount()-m_dwStart;
	UpdateData(FALSE);

	//you could decode the binary data here
	//the binary data contains various infos such as method ids, returned data, or error codes if available here

	delete []pBuffer;
	
	//Peek if any data is available
	dwBytes=0;
	IOCtl(FIONREAD, dwBytes);
	if(dwBytes && dwBytes >= sizeof(CStreamHeader))
	{
		while(!::PostMessage(CAsySocketClient::GetWnd(), WM_SOCKET_CLIENT_NOTIFY, m_hSocket, FD_READ))
		{
			::Sleep(1);
		}
	}
	return true;
}

void CSpeedTestDlg::OnConnectButton() 
{
	UpdateData(TRUE);

	//set application instance
	SetInstance(AfxGetApp()->m_hInstance);
	
	//create a local socket
	CAsySocket::Create(0);
	
	//connect the local socket to a server (m_strHost) listening socket (m_nPort) asynchronously
	//connection time out is 30 seconds by default. 
	//If you don't like this default, call the function CAsySocketClient::SetConnectTimeout
	Connect(m_strHost, m_nPort);	
}

void CSpeedTestDlg::OnClose(WPARAM hSocket,  LPARAM lError)
{
	GetDlgItem(IDC_ASYN_NAGLE_BUTTON)->EnableWindow(FALSE);
	GetDlgItem(IDC_ASYN_BATCH_BUTTON)->EnableWindow(FALSE);
	GetDlgItem(IDC_SYN_ONE_BUTTON)->EnableWindow(FALSE);
	
	m_bNagle=FALSE;

	UpdateData(FALSE);

	CAsySocketClient::OnClose(hSocket, lError);
}

void CSpeedTestDlg::OnConnect(WPARAM hSocket,  LPARAM lError)
{
	if(lError==S_OK)
	{
		DWORD	dwOldEvents=m_lEvent;
		
		GetDlgItem(IDC_ASYN_NAGLE_BUTTON)->EnableWindow(TRUE);
		GetDlgItem(IDC_ASYN_BATCH_BUTTON)->EnableWindow(TRUE);
		GetDlgItem(IDC_SYN_ONE_BUTTON)->EnableWindow(TRUE);
		
		CStreamHeader	StreamHeader;

		CPacking		Packing;

		StreamHeader.m_nValue=HOST_DNS_SVS_SOCKET;	//HostDNS class ID

		//switch to blocking mode, and make logical in coding simpler 
		AsyncSelect(0);

		//Remember that the SocketPro server can provide multiple svervices 
		//Tells the SocketPro server to switch to HostDNS service only
		SendBigChunk(&StreamHeader, sizeof(StreamHeader));
		
		//Get the returned result
		RecvBigChunk(&StreamHeader, sizeof(StreamHeader));
		if(StreamHeader.m_nValue!=S_OK)
		{
			MessageBox("No requried class recognized!");
		}

		//switch back to non-blocking mode, and don't need the event FD_CONNECT any more
		AsyncSelect(dwOldEvents &~(FD_CONNECT));

		m_bNagle=TRUE;

		UpdateData(FALSE);
	}
	else
	{
		CString strErrMsg;
		strErrMsg.Format("Error happens in connecting to a host, and error code =%d\n", lError);
		MessageBox(strErrMsg);
	}
}

void CSpeedTestDlg::OnDisconnectButton() 
{
	GetDlgItem(IDC_ASYN_NAGLE_BUTTON)->EnableWindow(FALSE);
	GetDlgItem(IDC_ASYN_BATCH_BUTTON)->EnableWindow(FALSE);
	GetDlgItem(IDC_SYN_ONE_BUTTON)->EnableWindow(FALSE);
	
	//gracefully shut down socket
	ShutDown();
//	Close();

	m_bNagle=FALSE;

	UpdateData(FALSE);
}

void CSpeedTestDlg::OnAsynNagleButton() 
{
	UpdateData(TRUE);
	m_dwStart=::GetTickCount();
	unsigned long	nIndex=0;
	m_nBytes=0;
	CStreamHeader	StreamHeader;
	StreamHeader.m_nLen=0;
	StreamHeader.m_nValue=HOST_DNS_SVS_METHOD_ID_GET_CLIENTS;
	
	//Coalescing happens automatically through Nagle algorithm
	//Multiple StreamHeaders are sent to a SocketPro server using one big stream.
	//You can watch the sizes of big streams at the server side.
	//This will reduce data round-trips for efficient use of network.
	for(nIndex=0; nIndex<m_nRepeat; nIndex++)
	{
		//Nagle algorithm may cost a little time, which depends on your machine
		SendBigChunk(&StreamHeader, sizeof(StreamHeader));
	}
	
	m_nNagleTime=::GetTickCount()-m_dwStart;
	UpdateData(FALSE);
}

void CSpeedTestDlg::OnAsynBatchButton() 
{
	UpdateData(TRUE);
	m_dwStart=::GetTickCount();
	m_nBytes=0;
	unsigned long	nIndex=0;
	CStreamHeader	*pStreamHeader=new CStreamHeader [m_nRepeat];
	for(nIndex=0; nIndex<m_nRepeat; nIndex++)
	{
		pStreamHeader[nIndex].m_nLen=0;
		pStreamHeader[nIndex].m_nValue=HOST_DNS_SVS_METHOD_ID_GET_CLIENTS;
	}

	//Coalescing by our code instead of Nagle algorithm
	//Multiple StreamHeaders are sent to a SocketPro server using one big stream.
	//You can watch the sizes of big streams at the server side.
	//This will reduce data round-trips for efficient use of network.
	SendBigChunk(pStreamHeader, m_nRepeat*sizeof(CStreamHeader));
	delete []pStreamHeader;
	m_nNagleTime=::GetTickCount()-m_dwStart;
	UpdateData(FALSE);
}

void CSpeedTestDlg::OnSynOneButton() 
{
	char	*strBuffer;
	unsigned long	nIndex;
	CStreamHeader	StreamHeader;

	//remember the old events
	DWORD	dwOldEvents=m_lEvent;
	UpdateData(TRUE);

	m_nBytes=0;

	//switch to blocking mode
	AsyncSelect(0);

	m_dwStart=::GetTickCount();

	for(nIndex=0; nIndex<m_nRepeat; nIndex++)
	{
		StreamHeader.m_nLen=0;
		StreamHeader.m_nValue=HOST_DNS_SVS_METHOD_ID_GET_CLIENTS;

		SendBigChunk(&StreamHeader, sizeof(StreamHeader));

		//Get the returned stream header 
		m_nBytes += RecvBigChunk(&StreamHeader, sizeof(StreamHeader));
		
		strBuffer = new char [StreamHeader.m_nLen];
		
		//Retrieve the binary data
		m_nBytes += RecvBigChunk(strBuffer, StreamHeader.m_nLen);
		
		delete []strBuffer;
	}

	m_dwTime=::GetTickCount()-m_dwStart;
	UpdateData(FALSE);
	
	//switch back to non-blocking mode
	AsyncSelect(dwOldEvents);
}

void CSpeedTestDlg::OnDestroy() 
{
	if(IsOpen())
	{
		OnDisconnectButton();
	}
	CDialog::OnDestroy();	
}

void CSpeedTestDlg::OnNagleCheck() 
{
	UpdateData(TRUE);
	m_dwStart=::GetTickCount();
	if(IsOpen())
	{
		CStreamHeader	StreamHeader;
		
		//Client side
/*		if(m_bNagle)
		{
			BOOL bNoDelay=(!m_bNagle);
			SetSockOpt(TCP_NODELAY, &bNoDelay, sizeof(bNoDelay), IPPROTO_TCP);
		}
		else
		{
			BOOL bNoDelay=(!m_bNagle);
			SetSockOpt(TCP_NODELAY, &bNoDelay, sizeof(bNoDelay), IPPROTO_TCP);
		}*/
		
		//Server side
		if(m_bNagle)
			StreamHeader.m_nValue=ENABLE_NAGLE;	//enable
		else
			StreamHeader.m_nValue=DISABLE_NAGLE;	//disable	

		SendBigChunk(&StreamHeader, sizeof(StreamHeader));
	}
}

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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Yuancai (Charlie) Ye
Web Developer
United States United States
Yuancai (Charlie) Ye, an experienced software engineer, lives in Atlanta, Georgia. He is an expert at OLEDB consumer and created a powerful data accessing libarary at the site http://www.udaparts.com. He has been working at SocketPro written from batching, asynchrony and parallel computation for more than three years. Visual C++, C# and ASP.NET are his favorite development environments.

You may also be interested in...

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150728.1 | Last Updated 24 Feb 2002
Article Copyright 2002 by Yuancai (Charlie) Ye
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid