Friday, April 28, 2006

No more Win32 for a while

I won't be coding any Win32 for a while as my computer just ended it's life and I'm not too keen on rejuvenating it 'cos the repairs cost a lot - I can get a new desktop for the price of repairing my notebook PC.

Anyway, hope you have a good time coding with the Win32 API.

Monday, April 24, 2006

It's been a while

I haven't posted since my blog was blocked after it was detected as spam. It was whitelisted after about 2 days, but then there were server problems and so I stepped away from blogging and from Win32 programming.

Now, I'm back and am hoping to get into Win32 for User Interfaces, Sockets, and Thread to develop a tiny chat application. I have a chat server/client that runs on Linux; this will be a complete re-write targeted at Windows (Win32 platform).

The first speed-bump I came across was using the 'how' constant for shutdown - the Linux equivalent wasn't supported and SD_BOTH worked only with Winsock2.h. It took me a while to figure out that I have to include Winsock2.h before Windows.h because Windows.h automatically includes Winsock.h.

Socket Programming in Win32

//Socket programming in Win32
//Author: Nitin Reddy Katkam



//---- chatty_ui.h ----

#ifndef _CHATTY_UI__H

#define _CHATTY_UI__H


#undef UNICODE
#undef _UNICODE
#define _WINSOCKAPI_ /* Prevent inclusion of winsock.h in windows.h */

#include
#include


LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void ExitWithError(char *ac_operation);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);

#endif




//---- chatty_sock.h ----

#ifndef _CHATTY_SOCK__H

#define _CHATTY_SOCK__H


#undef UNICODE
#undef _UNICODE

#include
#include

int initChattySock (char *ac_ipaddr);
void listenChatty ();
void ShutEar();
DWORD WINAPI ServerThreadProc( LPVOID lpParam );
#endif




//---- chatty_ui.cpp ----

#include "chatty_ui.h"
#include "chatty_sock.h"

HWND hwnd_edit_ip;
HWND hwnd_button_connect;
HINSTANCE hInstance_g;

char c_currStatus=0;

LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_COMMAND:
switch (wParam) {
case 2: //connect button
//MessageBox(NULL, "button pressed", "info", MB_OK);

c_currStatus=!c_currStatus;
if (c_currStatus) {
char buf[256];
GetWindowText(hwnd_edit_ip, buf, 256);
initChattySock(buf);
listenChatty();

SetWindowText(hwnd_button_connect, "Disconnect");
} else {
ShutEar();

SetWindowText(hwnd_button_connect, "Connect");
}

break;
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
exit(0);
break;
case WM_CREATE:
hwnd_edit_ip = CreateWindowEx(0, "edit", "0.0.0.0", WS_CHILD|WS_VISIBLE|WS_BORDER, 70, 45, 140, 25, hwnd, (HMENU) 1, hInstance_g, 0);
hwnd_button_connect = CreateWindowEx(0, "button", "Connect", WS_CHILD|WS_VISIBLE, 220, 45, 75, 25, hwnd, (HMENU) 2, hInstance_g, 0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}


void ExitWithError(char *ac_operation) {
printf("Error in %s\r\n", ac_operation);
getchar();
exit(1);
}


int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
hInstance_g=hInstance;
int callRetVal=0;

WNDCLASSEX wc;
PWNDCLASSEX p_wc = &wc;
int i_wcSize = sizeof(WNDCLASSEX);
memset(p_wc, 0, i_wcSize);

wc.cbSize=i_wcSize;
wc.lpszClassName="katkam_chatwin";
wc.lpfnWndProc=WndProc;
wc.hInstance=hInstance;
wc.hbrBackground=(HBRUSH) (COLOR_WINDOW+1);

callRetVal = RegisterClassEx(p_wc); //if the return value is zero, an error occurred
if (!callRetVal) {
ExitWithError("Window Registration");
}


HWND hwnd = CreateWindowEx(0, "katkam_chatwin", "K-Chat", WS_OVERLAPPEDWINDOW, 0, 0, 320, 200, NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);


MSG msg;
MSG *p_msg=&msg;
while (GetMessage(p_msg, hwnd, 0, 0)) {
TranslateMessage(p_msg);
DispatchMessage(p_msg);
}

return (int) msg.wParam;
}




//---- chatty_sock.cpp ----

#include "chatty_ui.h"
#include "chatty_sock.h"


SOCKET sock1;
SOCKET sock2;

struct sockaddr_in saddr_in;
struct sockaddr *p_saddr = (struct sockaddr *) &saddr_in;
int sockaddr_len = sizeof(struct sockaddr_in);
struct sockaddr_in saddr_in2;
struct sockaddr *p_saddr2 = (struct sockaddr *) &saddr_in2;

HANDLE hThread;


int initChattySock (char *ac_ipaddr) {
WSADATA wsaData;
if (WSAStartup(MAKEWORD(1,1), &wsaData) != 0) {
ExitWithError("WSAStartup");
//fprintf(stderr, "WSAStartup failed.\n");
//getchar();
//exit(1);
}

saddr_in.sin_addr.S_un.S_addr = inet_addr(ac_ipaddr);
saddr_in.sin_family=AF_INET;
saddr_in.sin_port=htons(1210);
memset(saddr_in.sin_zero, 0, 8);

sock1 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock1 == INVALID_SOCKET) {
ExitWithError("socket");
}

return 0;
}

void listenChatty () {
bind(sock1, p_saddr, sockaddr_len);
listen(sock1, 0);

DWORD dwThreadId;
hThread = CreateThread(NULL, 0, ServerThreadProc, NULL, 0, &dwThreadId);

}


void ShutEar() {
shutdown(sock1, SD_BOTH); //0x02 is for both read & write
closesocket(sock1);
shutdown(sock2, SD_BOTH); //0x02 is for both read & write
closesocket(sock2);
CloseHandle(hThread);
}


DWORD WINAPI ServerThreadProc( LPVOID lpParam ) {
sock2 = accept(sock1, p_saddr2, &sockaddr_len);
char buf[256];

strcpy(buf, "Hello\r\n"); // '\r' is carriage return; '\n' is line feed
send(sock2, buf, strlen(buf), 0);

return 0;
}