//***********************************************************
// 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;
}