Click here to Skip to main content
15,892,298 members
Articles / Mobile Apps / Windows Mobile

Power up the TCP/IP capability in your PocketPC application

Rate me:
Please Sign up or sign in to vote.
4.71/5 (17 votes)
19 Dec 2002CPOL3 min read 185K   323   55  
Establish a TCP/IP connection to other applications.
//***********************************************************
//				  WinSock Sample Application      		   //
//                                                         //
//                     Author : Chris C                    //
//   			        PassportONE.com			           //
//				 http://www.PassportONE.com/kb			   //
//			     Email:  chris@PassportONE.com			   //
//                       � Dec 2001                        //
//                                                         //
//***********************************************************

#include "MySocket.h"

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
	//  PURPOSE:  
	//		Main application message dispatch routing.
	//		Check for previous instance.
	//  PARAMETERS:
	//		- HINSTANCE
	//		- hPreviousInstance
	//		- pCmdLine
	//		- nCmdShow
	//  OPERATION:
	//		- Dispatch the received windows message
	//  RETURN VALUE:
	//      0/1

	MSG msg;

	// Update global variable
	hInst = hInstance;

	// Create Server and Client dialouge
	hWndServer = CreateDialog(hInst, MAKEINTRESOURCE(IDD_SERVER), NULL, (DLGPROC)ServerProc);

	if (hWndServer == NULL)
	{
		// Notified your about the failure
		MessageBox(NULL, TEXT("Fail to create dialouge!"), TEXT("MySocket"), MB_OK | MB_ICONEXCLAMATION);
		// Set the return value
		return false;
	}
	else
		// Display the dialouge
		ShowWindow(hWndServer, nCmdShow);

	// Main message loop:
	while (GetMessage(&msg, NULL, 0, 0)) 
	{
		if (!TranslateAccelerator(msg.hwnd, NULL, &msg)) 
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return msg.wParam;
}

LRESULT CALLBACK ServerProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	//  PURPOSE:  
	//		Server socket dialouge CALLBACK procedure.
	//  PARAMETERS:
	//		- HWND
	//		- message
	//		- wParam
	//		- lParam
	//  OPERATION:
	//		- Any windows related function/application functioncalling.
	//  RETURN VALUE:
	//      0/1

	char	data[1024];
	TCHAR	Buff[1024];

	switch (message) 
	{
		case WM_INITDIALOG:
			// Initialize the Winsock DLL
			if (InitSocket(hWnd) == 0)
				// Retrieve the Local PC IP address
				GetLocalIP(hWnd);
			
			// Set the default selection
			SendDlgItemMessage(hWnd, IDC_RADIO1, BM_SETCHECK, BST_CHECKED , 0);
			// Reset socket variable
			sckServer = INVALID_SOCKET;
			sckClient = INVALID_SOCKET;
			return true;
		case WM_COMMAND:
			switch (LOWORD(wParam))
			{
			case IDC_BUTTON1:
				// Listen/Connect
				OpenSocket(hWnd);
				break;
			case IDC_BUTTON2:
				// Close/Disconnect
				CloseSocket(hWnd);
				break;
			case IDC_BUTTON3:
				// Send
				if (sckClient != INVALID_SOCKET)
				{
					// Reset the string Buffer
					memset(Buff, TEXT('\0'), 1024*sizeof(TCHAR));
					memset(data, TEXT('\0'), 1024);
					// Get the user enter message
					GetDlgItemText(hWnd, IDC_EDIT4, Buff, 1024);
					// Convert from UNICODE to MultiByte Char
					wcstombs(data, Buff, 1024);
					// Send the data to client
					send(sckClient, data, 1024, 0);
					// Reset the user enter message
					SetDlgItemText(hWnd, IDC_EDIT4, TEXT(""));
				}
				else
					// Notify user about the error
					MessageBox(hWnd, TEXT("invalid socket state!"), TEXT("MySocket"), MB_OK | MB_ICONEXCLAMATION);				
				break;
			case IDC_RADIO1:
				// Server mode
				SetDlgItemText(hWnd, IDC_BUTTON1, TEXT("Listen"));
				SetDlgItemText(hWnd, IDC_BUTTON2, TEXT("Close"));
				SetDlgItemText(hWnd, IDC_ADDRESS, TEXT("Local IP Address:"));
				break;
			case IDC_RADIO2:
				// Client mode
				SetDlgItemText(hWnd, IDC_BUTTON1, TEXT("Connect"));
				SetDlgItemText(hWnd, IDC_BUTTON2, TEXT("Disconnect"));
				SetDlgItemText(hWnd, IDC_ADDRESS, TEXT("Server IP Address:"));
				break;
			}
			break;
		case WM_CLOSE:
			// Close any open server side socket
			CloseSocket(hWnd);
			// Close the window
			DestroyWindow(hWndServer);
			break;
		case WM_DESTROY:
			// Send the end program command
			PostQuitMessage(0);
			break;
		default:
			break;
   }
   return 0;
}

int InitSocket(HWND hWnd)
{
	//  PURPOSE:  
	//		Ensure the winsock related DLL is loaded and initialize
	//  PARAMETERS:
	//		- NIL
	//  OPERATION:
	//		- Call the WSAStartup API
	//  RETURN VALUE:
	//      - NIL
	
	WSADATA	wsaData;

	// Initliatize the Winsock dll version 1.1
	if (WSAStartup(MAKEWORD(1,1), &wsaData) != 0)
	{
		// Fail to initialize the winsock dll
		MessageBox(hWnd, TEXT("Fail to initialize the Winsock DLL!"), TEXT("MySocket"), MB_OK | MB_ICONEXCLAMATION);
		// Set the return value
		return 1;
	}
	else
		// Successful initialize the Winsock DLL
		// Set the return value
		return 0;
}

void GetLocalIP(HWND hWnd)
{
	//  PURPOSE:  
	//		- Obtain the current IP assign to the local PC
	//  PARAMETERS:
	//		- hWnd		:: Handle of the parent window.
	//  OPERATION:
	//		- Call the gethostname API
	//  RETURN VALUE:
	//      - NIL

	HOSTENT *LocalAddress;
	char	*Buff;
	TCHAR	*wBuff;


	// Create new string buffer
	Buff = new char[256];
	wBuff = new TCHAR[256];
	// Reset the string buffer
	memset(Buff, '\0', 256);
	memset(wBuff, TEXT('\0'), 256*sizeof(TCHAR));
	// Get computer name
	if (gethostname(Buff, 256) == 0)
	{
		// Convert computer name from MultiByte char to UNICODE
		mbstowcs(wBuff, Buff, 256);
		// Copy the machine name into the GUI control
		SetWindowText(GetDlgItem(hWnd, IDC_MACHINE), wBuff);
		// Get the local PC IP address
		LocalAddress = gethostbyname(Buff);
		// Reset the string buffer
		memset(Buff, '\0', 256);
		// Compose the obtain ip address
		sprintf(Buff, "%d.%d.%d.%d\0", LocalAddress->h_addr_list[0][0] & 0xFF, LocalAddress->h_addr_list[0][1] & 0x00FF, LocalAddress->h_addr_list[0][2] & 0x0000FF, LocalAddress->h_addr_list[0][3] & 0x000000FF);
		// Reset the wBuff
		memset(wBuff, TEXT('\0'), 256*sizeof(TCHAR));
		// Convert computer name from MultiByte char to UNICODE
		mbstowcs(wBuff, Buff, 256);
		// Set the ip address to edit control 1
		SetWindowText(GetDlgItem(hWnd, IDC_EDIT1), wBuff);
		// Set the default port number
		SetWindowText(GetDlgItem(hWnd, IDC_EDIT2), TEXT("5000"));
	}
	else
		// Notify user about the error
		MessageBox(hWnd, TEXT("Fail to get host name."), TEXT("MySocket"), MB_OK | MB_ICONEXCLAMATION);

	//
	delete Buff;
}

void OpenSocket(HWND hWnd)
{
	//  PURPOSE:  
	//		- Open the servcer side socket that will listen to a 
	//		  specific port number
	//  PARAMETERS:
	//		- hWnd		:: Handle of the parent window.
	//  OPERATION:
	//		- Call the socket and bind API
	//  RETURN VALUE:
	//      - NIL

	DWORD	dwThreadID = 0;
	//
	TCHAR	*whost = NULL;
	TCHAR	*wport = NULL;
	char	*host = NULL;
	char	*port = NULL;

	// Create a new string buffer
	wport = new TCHAR[16];
	port = new char[16];
	whost = new TCHAR[256];
	host = new char[256];

	memset(port, '\0', 16);
	memset(wport, TEXT('\0'), 16*sizeof(TCHAR));
	memset(host, '\0', 256);
	memset(whost, TEXT('\0'), 256*sizeof(TCHAR));

	// Get the current selected host & port number
	GetDlgItemText(hWnd, IDC_EDIT1, whost, 256);
	GetDlgItemText(hWnd, IDC_EDIT2, wport, 16);
	// Convert from UNICODE to MultiByte Char
	wcstombs(host, whost, 256);
	wcstombs(port, wport, 16);

	// Check user selection
	if (SendDlgItemMessage(hWnd, IDC_RADIO1, BM_GETCHECK, 0, 0) == BST_CHECKED)
	{
		// Server side socket
		// Update window text
		SetWindowText(hWnd, TEXT("Winsock... [Server]"));
		// Create the listen thread
		hThread1 = CreateThread(NULL, 0, StartListen, hWnd, 0, &dwThreadID);
	}
	else
	{
		// Client side socket
		// Update window text
		SetWindowText(hWnd, TEXT("Winsock... [Client]"));
		// Reset the SOCKADDR_IN struct
		memset(&sckAddress, 0, sizeof(sockaddr_in));
		// Setup the sckClient socket
		sckClient = socket(AF_INET, SOCK_STREAM, 0);
		sckAddress.sin_port = htons(atoi(port));
		sckAddress.sin_family = AF_INET;
		sckAddress.sin_addr.s_addr = inet_addr(host);
		if(connect(sckClient, (struct sockaddr *)&sckAddress, sizeof(sckAddress)) != SOCKET_ERROR)
		{
			// Enable/Disable control
			EnableWindow(GetDlgItem(hWnd, IDC_EDIT1), false);
			EnableWindow(GetDlgItem(hWnd, IDC_EDIT2), false);
			EnableWindow(GetDlgItem(hWnd, IDC_EDIT3), true);
			EnableWindow(GetDlgItem(hWnd, IDC_EDIT4), true);
			EnableWindow(GetDlgItem(hWnd, IDC_BUTTON1), false);
			EnableWindow(GetDlgItem(hWnd, IDC_BUTTON2), true);
			EnableWindow(GetDlgItem(hWnd, IDC_BUTTON3), true);
			EnableWindow(GetDlgItem(hWnd, IDC_RADIO1), false);
			EnableWindow(GetDlgItem(hWnd, IDC_RADIO2), false);			
			// Update display
			SetDlgItemText(hWnd, IDC_STATUS1, TEXT("Connected"));
			// Create read input buffer thread
			hThread2 = CreateThread(NULL, 0, ReadInBuffer, hWnd, 0, &dwThreadID);
		}
		else
			// Notify user about the error
			MessageBox(hWnd, TEXT("Client~Fail to establish the connection!"), TEXT("MySocket"), MB_OK | MB_ICONEXCLAMATION);

	}

	// Release the use memory
	delete [] whost;
	delete [] host;
	delete [] wport;
	delete [] port;
}

void CloseSocket(HWND hWnd)
{
	//  PURPOSE:  
	//		- Close s server side socket.
	//  PARAMETERS:
	//		- hWnd		:: Handle of the parent window.
	//  OPERATION:
	//		- Call the socket and bind API
	//  RETURN VALUE:
	//      - NIL

	TCHAR	*Buff;
	// Create a new string buffer
	Buff = new TCHAR[16];
	// Reset the string buffer
	memset(Buff, TEXT('\0'), 16*sizeof(TCHAR));

	// Update window text
	SetWindowText(hWnd, TEXT("Winsock..."));

	// Get the connection status
	GetDlgItemText(hWnd, IDC_STATUS1,Buff, 16);
	// Check user selection
	if (wcscmp(Buff, TEXT("Connected")) != 0)
	{
		// Validate
		if(sckServer != INVALID_SOCKET)
		{
			// Close the current server side socket
			if (closesocket(sckServer) == 0)
			{
				// Enable/Disable control
				EnableWindow(GetDlgItem(hWnd, IDC_EDIT1), true);
				EnableWindow(GetDlgItem(hWnd, IDC_EDIT2), true);
				EnableWindow(GetDlgItem(hWnd, IDC_EDIT3), false);
				EnableWindow(GetDlgItem(hWnd, IDC_EDIT4), false);
				EnableWindow(GetDlgItem(hWnd, IDC_BUTTON1), true);
				EnableWindow(GetDlgItem(hWnd, IDC_BUTTON2), false);
				EnableWindow(GetDlgItem(hWnd, IDC_BUTTON3), false);
				EnableWindow(GetDlgItem(hWnd, IDC_RADIO1), true);
				EnableWindow(GetDlgItem(hWnd, IDC_RADIO2), true);

				// Update display
				SetDlgItemText(hWnd, IDC_STATUS1, TEXT("Idle"));
				// Reset the sckServer
				sckServer = INVALID_SOCKET;
			}
			else
				// Notify user about the error
				MessageBox(hWnd, TEXT("Server~Fail to close the socket."), TEXT("MySocket"), MB_OK | MB_ICONEXCLAMATION);
		}
	}
	else
	{
		// Validation
		if(sckClient != INVALID_SOCKET)
		{
			// Close the current server side socket
			if (closesocket(sckClient) == 0)
			{
				// Enable/Disable control
				EnableWindow(GetDlgItem(hWnd, IDC_EDIT1), true);
				EnableWindow(GetDlgItem(hWnd, IDC_EDIT2), true);
				EnableWindow(GetDlgItem(hWnd, IDC_EDIT3), false);
				EnableWindow(GetDlgItem(hWnd, IDC_EDIT4), false);
				EnableWindow(GetDlgItem(hWnd, IDC_BUTTON1), true);
				EnableWindow(GetDlgItem(hWnd, IDC_BUTTON2), false);
				EnableWindow(GetDlgItem(hWnd, IDC_BUTTON3), false);
				EnableWindow(GetDlgItem(hWnd, IDC_RADIO1), true);
				EnableWindow(GetDlgItem(hWnd, IDC_RADIO2), true);

				// Update display
				SetDlgItemText(hWnd, IDC_STATUS1, TEXT("Idle"));
				// Reset the sckServer
				sckServer = INVALID_SOCKET;
				// Terminate the ReadInBuffer thread
				TerminateThread(hThread2, WM_QUIT);
			}
			else
				// Notify user about the error
				MessageBox(hWnd, TEXT("Fail to close the socket."), TEXT("MySocket"), MB_OK | MB_ICONEXCLAMATION);
		}
	}
}

DWORD WINAPI StartListen(LPVOID pParam)
{
	//  PURPOSE:  
	//		- Start waiting for the incoming connection request
	//  PARAMETERS:
	//		- hWnd		:: Handle of the parent window.
	//  OPERATION:
	//		- Call the "select" winsock API
	//  RETURN VALUE:
	//      - NIL

	DWORD	dwThreadID = 0;
	HWND	hWnd = NULL;

	char	*port = NULL;
	TCHAR	*wport = NULL;

	// Socket callback status structure
	fd_set  fds;
	// Maximum wait time for the "select" command
	timeval tv; 

	// map the pass in variable
	hWnd = (HWND)pParam;

	// Create a new string buffer
	port = new char[16];
	wport = new TCHAR[16];
	
	memset(port, '\0', 16);
	memset(wport, TEXT('\0'), 16*sizeof(TCHAR));

	// Get the current selected host & port number
	GetDlgItemText(hWnd, IDC_EDIT2, wport, 16);
	// Convert from UNICODE to MultiByte Char
	wcstombs(port, wport, 16);

	// Create a server socket
	sckServer = socket(AF_INET, SOCK_STREAM, 0);
	// Validation
	if(sckServer != INVALID_SOCKET)
	{
		// Setup the port number, protocol & etc..
		sckAddress.sin_port = htons(atoi(port));
		sckAddress.sin_family= AF_INET;
		sckAddress.sin_addr.s_addr = INADDR_ANY;
		// Bind the socket
		bind(sckServer, (struct sockaddr *)&sckAddress, sizeof(sckAddress));	

		// Update display
		SetDlgItemText(hWnd, IDC_STATUS1, TEXT("Listen"));
		// Enable/Disable control
		EnableWindow(GetDlgItem(hWnd, IDC_EDIT1), false);
		EnableWindow(GetDlgItem(hWnd, IDC_EDIT2), false);
		EnableWindow(GetDlgItem(hWnd, IDC_EDIT3), true);
		EnableWindow(GetDlgItem(hWnd, IDC_EDIT4), true);
		EnableWindow(GetDlgItem(hWnd, IDC_BUTTON1), false);
		EnableWindow(GetDlgItem(hWnd, IDC_BUTTON2), true);
		EnableWindow(GetDlgItem(hWnd, IDC_BUTTON3), true);
		EnableWindow(GetDlgItem(hWnd, IDC_RADIO1), false);
		EnableWindow(GetDlgItem(hWnd, IDC_RADIO2), false);

		// Listen to the specific port
		listen(sckServer, 1);

		// Start looping and check the respective port for incoming request
		do
		{
			// Socket callback status structure
			fds;
			// Maximum wait time for the "select" command
			tv.tv_sec = 1;
			tv.tv_usec = 1; 
			// Initialize the fd_set structure to NULL
			FD_ZERO (&fds);
			// Add the sckServer socket to fd_set structure
			FD_SET (sckServer, &fds);
			// Call the select command
			if (select(0, &fds, NULL, NULL, &tv) == 0)
				// Maximum wait time is expired.
				continue;
			// Check is there any incoming request/active in the fd_set structure
			// Zero mean no, else
			if (FD_ISSET(sckServer, &fds) != 0)
			{
				// Accept the incoming request
				sckClient = accept(sckServer, NULL, 0);
				// Close the existing listen socket (sckServer)
				closesocket(sckServer);
				// Reset the sckSocket variable to NULL
				sckServer = INVALID_SOCKET;
				// Update status control
				SetDlgItemText(hWnd, IDC_STATUS1, TEXT("Connected"));
				// Create read input buffer thread
				hThread2 = CreateThread(NULL, 0, ReadInBuffer, hWnd, 0, &dwThreadID);
				// Self terminate this thread
				break;
			}
		}while (sckServer != INVALID_SOCKET);
	}
	else
		// Notify user about the error
		MessageBox(hWnd, TEXT("Server~Fail to open the socket!"), TEXT("MySocket"), MB_OK | MB_ICONEXCLAMATION);	
	
	// Release all the use memory
	delete [] port;
	delete [] wport;

	// Self terminate the thread
	ExitThread(WM_QUIT);

	// Set the return value
	return 0;
}

DWORD WINAPI ReadInBuffer(LPVOID pParam)
{
	//  PURPOSE:  
	//		- Read any incoming data as well as detect the connected lost/reset
	//  PARAMETERS:
	//		- hWnd		:: Handle of the parent window.
	//  OPERATION:
	//		- Call the "recv" winsock API
	//  RETURN VALUE:
	//      - NIL

	HWND	hWnd = NULL;
	char	*Buff=NULL;
	TCHAR	*wBuff=NULL;

    int		err;

	// map the pass in variable
	hWnd = (HWND)pParam;
	// Create new string buffer
	wBuff = new TCHAR[1024];
	Buff = new char[1024];

    if (sckClient != INVALID_SOCKET )
    {
        // Loop until no data in the input buffer
        while (true)
        {
			// Reset the allocated string buffer
			memset(wBuff, TEXT('\0'), 1024*sizeof(TCHAR));
			memset(Buff, '\0', 1024);
			// Read the data from valid socket
            err = recv(sckClient, Buff, 1024, 0);
            if (err == SOCKET_ERROR || err <= 0)
			{
				// Remote terminal reset the socket connection
				CloseSocket(hWnd);
				// Self terminate the thread
				break;
			}
			else
			{
				// Convert from MultiByte to UNICODE
				mbstowcs(wBuff, Buff, 1024);
				// Display the received data
				SetDlgItemText(hWnd, IDC_EDIT3, wBuff);
			}
        }
    }

	// Release the used memory
	delete Buff;
	// Self terminate the thread
	ExitThread(WM_QUIT);

	// Set the return value
	return 0;
}

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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Australia Australia
Passion to be a software architect and solution researcher in enterprise solutions by simplify and unify the existing complex manual paper works into an automated environment friendly, comprehensive and dynamic workflow process system.

Comments and Discussions