C Board  

Go Back   C Board > Platform Specific Boards > Windows Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 12-28-2004, 10:58 AM   #1
Registered User
 
Join Date: Aug 2004
Posts: 307
Where do I initialize Winsock and catch messages for it?

I am writing a piece of code for asynchronious chatting (If you saw my last thread on this, it's the same engine, GUI-fied rather than working with writing my own curses library). However, I cannot seem to figure out two things:

1.) Where do I init Winsock so that my program can fully use it without dropping the connection /immediately/ after accepting it, and

2.) Is there a way to handle connections without opening a new thread every single time to do so?

I have a feeling if #2 is solved that #1 will fall into place, but I don't know. Here's the code..

Code:
#include <windows.h>
#include <iostream>

// Window dialog definations

#define ID_FILE_LISTEN	1
#define ID_FILE_SLISTEN	2
#define ID_FILE_EXIT	3

#define ID_ABOUT_HELP	20

#define IDC_EDITI		101
#define IDC_EDITO		102
#define IDC_BTNS		103

#define SOCKET_READY	 0x40000

// Functions

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
int startWsk(SOCKET sClient);

// Variables

const char g_szClassName[] = "myWindowClass";

WNDCLASSEX wc;
HMENU hMenu, hSubMenu;
HWND hWnd, hEditIn, hEditOut, hBtnSend;
RECT rcClient;
MSG Msg;

// Code

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	wc.cbSize		 = sizeof(WNDCLASSEX);
	wc.style		 = 0;
	wc.lpfnWndProc	 = WndProc;
	wc.cbClsExtra	 = 0;
	wc.cbWndExtra	 = 0;
	wc.hInstance	 = hInstance;
	wc.hIcon		 = LoadIcon(NULL, IDI_APPLICATION);
	wc.hCursor		 = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wc.lpszMenuName  = NULL;
	wc.lpszClassName = g_szClassName;
	wc.hIconSm		 = LoadIcon(NULL, IDI_APPLICATION);

	if(!RegisterClassEx(&wc))
	{
		MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
		return(0);
	}

	hWnd = CreateWindowEx(NULL, g_szClassName, "Lithnet Chat", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 300, 600, NULL, NULL, hInstance, NULL);

	if(hWnd == NULL)
	{
		MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
		return(0);
	}

	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);
	
	while(GetMessage(&Msg, NULL, 0, 0) > 0)
	{
		TranslateMessage(&Msg);
		DispatchMessage(&Msg);
	}
	return Msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	SOCKET sClient;
	
	switch(msg)
	{
		case WM_CREATE:
			
			hMenu = CreateMenu();

			hSubMenu = CreatePopupMenu();
			AppendMenu(hSubMenu, MF_STRING, ID_FILE_LISTEN, "&Listen");
			AppendMenu(hSubMenu, MF_STRING, ID_FILE_SLISTEN, "&Stop Listening");
			AppendMenu(hSubMenu, MF_SEPARATOR, NULL, NULL);
			AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, "E&xit");
			AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&File");
			
			hSubMenu = CreatePopupMenu();
			AppendMenu(hSubMenu, MF_STRING, ID_ABOUT_HELP, "&About");
			AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&Help");
	
			SetMenu(hWnd, hMenu);	
		
			hEditIn = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL, 0, 0, 294, 500, hWnd, (HMENU)IDC_EDITI, GetModuleHandle(NULL), NULL);
		
			if(hEditIn == NULL)
			{
				MessageBox(hWnd, "Could not create edit box.", "Error", MB_OK | MB_ICONERROR);
			}
			 
			hEditOut = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL, 0, 500, 244, 55, hWnd, (HMENU)IDC_EDITO, GetModuleHandle(NULL), NULL);
		
			if(hEditOut == NULL)
			{
				MessageBox(hWnd, "Could not create edit box.", "Error", MB_OK | MB_ICONERROR);
			}
			
			hBtnSend = CreateWindowEx(WS_EX_CLIENTEDGE, "BUTTON", NULL, WS_CHILD | WS_VISIBLE, 244, 500, 50, 55, hWnd, (HMENU)IDC_BTNS, GetModuleHandle(NULL), NULL);
		
			if(hBtnSend == NULL)
			{
				MessageBox(hWnd, "Could not create edit box.", "Error", MB_OK | MB_ICONERROR);
			}
			 
		break;
		
		case WM_SIZE:
    	{
        	SetDlgItemText(hWnd, IDC_BTNS, "Send");
    	}
    	break;
		
		case WM_CLOSE:
			DestroyWindow(hWnd);
		break;
		
		case WM_DESTROY:
			PostQuitMessage(0);
		break;
		
		case WM_COMMAND:
			switch(LOWORD(wParam))
			{
				case ID_FILE_LISTEN:
					startWsk(sClient);
				break;
				
				case ID_FILE_SLISTEN:
					WSACleanup();
				break;
				
				case ID_FILE_EXIT:
					PostQuitMessage(0);
				break;
				
				case ID_ABOUT_HELP:
					MessageBox(NULL, "Programmer: Steven Merrick", "About Lithnet Chat", NULL);
				break;
			}
		break;
		
		case SOCKET_READY: 
			char buffer[256];
			
			memset(buffer, 0, sizeof(buffer));
			recv(sClient, buffer, sizeof(buffer), 0); 
			
			if (buffer[0] != NULL) // If the buffer is not empty..
			{
				SetDlgItemText(hWnd, IDC_EDITI, buffer);
			}
		break;
		
		default:
			return DefWindowProc(hWnd, msg, wParam, lParam);
	}
	return 0;
}

int startWsk(SOCKET sClient)
{
	/* Winsock */
	
	int tmp;
	char buffer[256];
	
	WSADATA wsaData; // Windows Socket Data.
	SOCKET sListen; // Create listening socket.
	SOCKADDR_IN sInfo;
		sInfo.sin_family = AF_INET; // Internet.
		sInfo.sin_addr.s_addr = INADDR_ANY; // Any incoming address.
		sInfo.sin_port = htons(10000); // Port 10000.
	
	tmp = WSAStartup(MAKEWORD(1,1), &wsaData); // Initialize Winsock 1.1.
	
	if (tmp == SOCKET_ERROR)
	{
		MessageBox(NULL, "Error in initializing Winsock", (LPCSTR)WSAGetLastError(), NULL); // Cout an error message.
		WSACleanup(); // Shutdown Winsock
	}
	
	sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // Create an Internet Steam TCP Socket.
	
	if (sListen == INVALID_SOCKET) 
	{
		MessageBox(NULL, "Error in creating socket", (LPCSTR)WSAGetLastError(), NULL); // Cout an error message.
		WSACleanup(); // Shutdown Winsock
	}
		
	tmp = bind(sListen, (LPSOCKADDR)&sInfo, sizeof(struct sockaddr));
	
	if (tmp == SOCKET_ERROR)
	{
		MessageBox(NULL, "Error in binding socket", (LPCSTR)WSAGetLastError(), NULL); // Cout an error message.
		WSACleanup(); // Shutdown Winsock
	}
	
	tmp = listen(sListen, 1);
	
	if (tmp == SOCKET_ERROR)
	{
		MessageBox(NULL, "Error in listening", (LPCSTR)WSAGetLastError(), NULL); // Cout an error message.
		WSACleanup(); // Shutdown Winsock
	}
	
	sClient = accept(sListen, NULL, NULL);
	
	if (sClient == SOCKET_ERROR)
	{
		MessageBox(NULL, "Error in accepting", (LPCSTR)WSAGetLastError(), NULL); // Cout an error message.
		WSACleanup(); // Shutdown Winsock
	}
	
	/* End Winsock */
	
	WSAAsyncSelect(sClient, hWnd, SOCKET_READY, FD_READ);
	
	return(0);
}
Lithorien is offline   Reply With Quote
Old 12-28-2004, 03:22 PM   #2
Magically delicious
 
LuckY's Avatar
 
Join Date: Oct 2001
Posts: 856
1) You initialize Winsock once during the life of your program and usually somewhere near the beginning (in execution time not source code geography).

2) There is a way to do this. Since you're using Windows API you can use it's asynchronous sockets to receive messages for socket events. I have used CAsyncSocket in the past with success and ease (if you use MFC you might want to look into it), but I prefer to use my own socket library that directly uses a new thread for each client connection. Look into WSAAsyncSelect().

[edit]
Take a look at this thread.
[/edit]

Last edited by LuckY; 12-28-2004 at 03:27 PM.
LuckY is offline   Reply With Quote
Old 12-29-2004, 12:18 PM   #3
I am me, who else?
 
Join Date: Oct 2002
Posts: 250
Incidentally from what I see in your code you are simply catching Read events. You are not also checking for the WSAEWOULDBLOCK error, but its always a good thing to do, especially if the client wants to write back. Also it looks like the socket is a local variable within startWsk, so as soon as you init it, and move out of the scope you don't have a "reference" to it any more (poor choice of words, but can't think of anything else). In any event, you might also want to watch out for just displaying whatever is in the buffer. Also, this may or may not affect you but when I zero'd a buffer before I used it, I would never get anythign placed into the buffer and therefore each read event generated would provide me with nothing. Also, you should always check return values from recv and check WSAGetLastError() every so often if the return values for these functions are equal to SOCKET_ERROR (defined in winsock.h) because there can be a lot of problems that can be solved by finding the return values from send, recv, and the like and then calling WSAGetLastError() to get the error code. I don't know how many times that has helped me narrow down a problem in my winsock code. Anyway, advice from someone learning it as we speak. Hope these tips help you get past pitfalls I got into.
dpro is offline   Reply With Quote
Old 12-29-2004, 01:40 PM   #4
Registered User
 
Join Date: Aug 2004
Posts: 307
I've been editing the code a little, but it doesn't appear to have done a whole heck of a lot of good. From my test console project, the connection appears to be being /accepted/, but FD_READ isn't getting a single thing.

As for checking for WSAEWOULDBLOCK, where would I do that in the code? Just before or after recv()?

Code:
// Lithnet Chat
// Version 0.1s
// By: Steven Merrick

#include <windows.h>
#include <iostream>

// Window dialog definations

#define ID_FILE_LISTEN	1
#define ID_FILE_SLISTEN	2
#define ID_FILE_EXIT	3

#define ID_ABOUT_HELP	10

#define IDC_EDITI		101
#define IDC_EDITO		102
#define IDC_BTNS		103

#define SOCKET_READY	 0x40000

// Functions

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

// Variables

const char g_szClassName[] = "myWindowClass";
char buffer[256];
int tmp;

SOCKET sListen, sClient; // Create listening socket.
WNDCLASSEX wc;
HMENU hMenu, hSubMenu;
HWND hWnd, hEditIn, hEditOut, hBtnSend;
RECT rcClient;
MSG Msg;

// Code

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	wc.cbSize		 = sizeof(WNDCLASSEX);
	wc.style		 = 0;
	wc.lpfnWndProc	 = WndProc;
	wc.cbClsExtra	 = 0;
	wc.cbWndExtra	 = 0;
	wc.hInstance	 = hInstance;
	wc.hIcon		 = LoadIcon(NULL, IDI_APPLICATION);
	wc.hCursor		 = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wc.lpszMenuName  = NULL;
	wc.lpszClassName = g_szClassName;
	wc.hIconSm		 = LoadIcon(NULL, IDI_APPLICATION);

	if(!RegisterClassEx(&wc))
	{
		MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
		return(0);
	}

	hWnd = CreateWindowEx(NULL, g_szClassName, "Lithnet Chat", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 300, 600, NULL, NULL, hInstance, NULL);

	if(hWnd == NULL)
	{
		MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
		return(0);
	}

	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);
	
	WSADATA wsaData; // Windows Socket Data.
		
	tmp = WSAStartup(MAKEWORD(1,1), &wsaData); // Initialize Winsock 1.1.
	
	if (tmp == SOCKET_ERROR)
	{
		MessageBox(NULL, "Error in initializing Winsock", (LPCSTR)WSAGetLastError(), NULL); // Cout an error message.
		WSACleanup(); // Shutdown Winsock
	}
	
	WSAAsyncSelect(sClient, hWnd, SOCKET_READY, FD_WRITE | FD_ACCEPT | FD_CONNECT | FD_READ | FD_CLOSE);
	
	while(GetMessage(&Msg, NULL, 0, 0) > 0)
	{
		TranslateMessage(&Msg);
		DispatchMessage(&Msg);
	}
	return Msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{	
	switch(msg)
	{
		case WM_CREATE:
			hMenu = CreateMenu();

			hSubMenu = CreatePopupMenu();
			AppendMenu(hSubMenu, MF_STRING, ID_FILE_LISTEN, "&Listen");
			AppendMenu(hSubMenu, MF_STRING, ID_FILE_SLISTEN, "&Stop Listening");
			AppendMenu(hSubMenu, MF_SEPARATOR, NULL, NULL);
			AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, "E&xit");
			AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&File");
			
			hSubMenu = CreatePopupMenu();
			AppendMenu(hSubMenu, MF_STRING, ID_ABOUT_HELP, "&About");
			AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&Help");
	
			SetMenu(hWnd, hMenu);	
		
			hEditIn = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL, 0, 0, 294, 500, hWnd, (HMENU)IDC_EDITI, GetModuleHandle(NULL), NULL);
		
			if(hEditIn == NULL)
			{
				MessageBox(hWnd, "Could not create edit box.", "Error", MB_OK | MB_ICONERROR);
			}
			 
			hEditOut = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL, 0, 500, 244, 55, hWnd, (HMENU)IDC_EDITO, GetModuleHandle(NULL), NULL);
		
			if(hEditOut == NULL)
			{
				MessageBox(hWnd, "Could not create edit box.", "Error", MB_OK | MB_ICONERROR);
			}
			
			hBtnSend = CreateWindowEx(WS_EX_CLIENTEDGE, "BUTTON", NULL, WS_CHILD | WS_VISIBLE, 244, 500, 50, 55, hWnd, (HMENU)IDC_BTNS, GetModuleHandle(NULL), NULL);
		
			if(hBtnSend == NULL)
			{
				MessageBox(hWnd, "Could not create button.", "Error", MB_OK | MB_ICONERROR);
			}
		break;
		
		case WM_SIZE:
    	   	SetDlgItemText(hWnd, IDC_BTNS, "Send");
    	break;
		
		case WM_CLOSE:
			DestroyWindow(hWnd);
		break;
		
		case WM_DESTROY:
			PostQuitMessage(0);
		break;
		
		case WM_COMMAND:
			switch(LOWORD(wParam))
			{
				case ID_FILE_LISTEN:
				
					sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // Create an Internet Steam TCP Socket.
					
					if (sListen == INVALID_SOCKET) 
					{
						MessageBox(NULL, "Error in creating socket", (LPCSTR)WSAGetLastError(), NULL); // Cout an error message.
						WSACleanup(); // Shutdown Winsock
					}
					
					SOCKADDR_IN sInfo;
						sInfo.sin_family = AF_INET; // Internet.
						sInfo.sin_addr.s_addr = INADDR_ANY; // Any incoming address.
						sInfo.sin_port = htons(10000); // Port 10000.
						
					tmp = bind(sListen, (LPSOCKADDR)&sInfo, sizeof(struct sockaddr));
					
					if (tmp == SOCKET_ERROR)
					{
						MessageBox(NULL, "Error in binding socket", (LPCSTR)WSAGetLastError(), NULL); // Cout an error message.
						WSACleanup(); // Shutdown Winsock
					}
					
					tmp = listen(sListen, 1);
	
					if (tmp == SOCKET_ERROR)
					{
						MessageBox(NULL, "Error in listening", (LPCSTR)WSAGetLastError(), NULL); // Cout an error message.
						WSACleanup(); // Shutdown Winsock
					}
				break;
				
				case ID_FILE_SLISTEN:
					closesocket(sClient);
					closesocket(sListen);
					WSACleanup();
				break;
				
				case ID_FILE_EXIT:
					PostQuitMessage(0);
				break;
				
				case ID_ABOUT_HELP:
					MessageBox(NULL, "Programmer: Steven Merrick", "About Lithnet Chat", NULL);
				break;
			}
		break;
		
		case SOCKET_READY: 
			switch (LOWORD(lParam))
			{
				case FD_READ:
					if (recv(sClient, buffer, sizeof(buffer), 0) == SOCKET_ERROR)
					{
						MessageBox(NULL, "Error in recv()", "Error", NULL);
					}
					
					SetDlgItemText(hWnd, IDC_EDITO, buffer);
				break;
				
				case FD_ACCEPT:
					sClient = accept(sListen, NULL, NULL);
			
					if (sClient == SOCKET_ERROR)
					{
						MessageBox(NULL, "Error in accepting", (LPCSTR)WSAGetLastError(), NULL); // Cout an error message.
						WSACleanup(); // Shutdown Winsock
					}
				break;
			}
		break;
				
		default:
			return DefWindowProc(hWnd, msg, wParam, lParam);
	}

	return (0);
}
Lithorien is offline   Reply With Quote
Old 12-29-2004, 02:13 PM   #5
Registered User
 
Join Date: Sep 2004
Location: California
Posts: 2,845
Code:
tmp == SOCKET_ERROR
WSAStartup() doesn't return SOCKET_ERROR on failure, it returns a non-zero integer.

Code:
WSAAsyncSelect(sClient, hWnd, SOCKET_READY, FD_WRITE | FD_ACCEPT | FD_CONNECT | FD_READ | FD_CLOSE);
Ack, the socket hasn't been created yet. You need to create the socket with a socket() command before you use it.
bithub is offline   Reply With Quote
Old 12-29-2004, 02:16 PM   #6
I am me, who else?
 
Join Date: Oct 2002
Posts: 250
As I was writing this Bithub replied, so he basically said what I was gonna say

....


It looks like you cut out the whole of the startWsk function in your program. What needs to happen is that you still need to either bind to a port(server) or needs to connect to the server still (client). Or if peer to peer, need to do something a little different altogether. Anyway, it looks like you cleaned that up, but you are missing some key winsock functions (unless I am blind) I do not see a connect, or you filling in a sockaddr struct at all (which I understand is a necessary thing to do, and I can see why, but I don't have a solid explanation for it, more than likely it has to do with the fact that you need to keep that address around so you can reference it later on). In any event, I see you made the Socket global, which in this case is fine, I think your next step is to fill a sockaddr struct (check around for some tutorials or check out the link lucky posted).

In any event you need to get all the things (socket, sockaddr, listen/connect) setup.

Hope this helps.
dpro is offline   Reply With Quote
Old 12-29-2004, 02:24 PM   #7
Registered User
 
Join Date: Sep 2004
Location: California
Posts: 2,845
dpro >> He moved that code to menu event handler.
bithub is offline   Reply With Quote
Old 12-29-2004, 02:34 PM   #8
I am me, who else?
 
Join Date: Oct 2002
Posts: 250
I knew I would misread something sorry for misstating..

hows it going anyway? is it working better now or working at all?

Last edited by dpro; 12-29-2004 at 02:43 PM.
dpro is offline   Reply With Quote
Old 12-29-2004, 07:14 PM   #9
Registered User
 
Join Date: Dec 2004
Posts: 95
Using WSAAsyncSelect there's no need for any thread creation.

Other methods require it, however.

As for thread-per-connection (with blocking sockets I assume): this method doesn't scale, so it's not perhaps the best choice. It is easy to do, however.
azteched is offline   Reply With Quote
Old 12-29-2004, 09:54 PM   #10
Registered User
 
Join Date: Aug 2004
Posts: 307
IT WORKS!!! And since I am getting very annoyed with the threads that don't show the final working code, here it is:

Code:
// Lithnet Chat
// Version 0.1s
// By: Steven Merrick

#include <windows.h>
#include <iostream>

// Window dialog definations

#define ID_FILE_LISTEN	1
#define ID_FILE_SLISTEN	2
#define ID_FILE_EXIT	3

#define ID_ABOUT_HELP	10

#define IDC_EDITI		101
#define IDC_EDITO		102
#define IDC_BTNS		103

#define SOCKET_READY	WM_USER+1

// Functions

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

// Variables

const char g_szClassName[] = "myWindowClass";

WNDCLASSEX wc;
HMENU hMenu, hSubMenu;
HWND hWnd, hEditIn, hEditOut, hBtnSend;
SOCKET sListen, sClient; // Create listening socket.
RECT rcClient;
MSG Msg;

// Code

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{	
	wc.cbSize		 = sizeof(WNDCLASSEX);
	wc.style		 = 0;
	wc.lpfnWndProc	 = WndProc;
	wc.cbClsExtra	 = 0;
	wc.cbWndExtra	 = 0;
	wc.hInstance	 = hInstance;
	wc.hIcon		 = LoadIcon(NULL, IDI_APPLICATION);
	wc.hCursor		 = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wc.lpszMenuName  = NULL;
	wc.lpszClassName = g_szClassName;
	wc.hIconSm		 = LoadIcon(NULL, IDI_APPLICATION);

	if(!RegisterClassEx(&wc))
	{
		MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
		return(0);
	}

	hWnd = CreateWindowEx(NULL, g_szClassName, "Lithnet Chat - Server", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 300, 600, NULL, NULL, hInstance, NULL);

	if(hWnd == NULL)
	{
		MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
		return(0);
	}
	
	/* Winsock Setup */
	
	WSADATA wsaData; // Windows Socket Data.
					
	if (WSAStartup(MAKEWORD(1,1), &wsaData) != 0)
	{
		MessageBox(NULL, "Error in initializing Winsock", "Error!", NULL);
		WSACleanup();
	}
	
	SOCKADDR_IN sInfo;
		sInfo.sin_family = AF_INET; // Internet.
		sInfo.sin_addr.s_addr = INADDR_ANY; // Any incoming address.
		sInfo.sin_port = htons(10000); // Port 10000.
	
	sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // Create an Internet Steam TCP Socket.
	
	if (sListen == INVALID_SOCKET) 
	{
		MessageBox(NULL, "Error in creating socket", "Error!", NULL);
		WSACleanup();
	}
	
	if (bind(sListen, (LPSOCKADDR)&sInfo, sizeof(struct sockaddr)) == SOCKET_ERROR)
	{
		MessageBox(NULL, "Error in binding socket", "Error!", NULL);
		WSACleanup();
	}
	
	/* End Winsock Setup */

	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);
	
	WSAAsyncSelect(sListen, hWnd, SOCKET_READY, FD_ACCEPT | FD_READ | FD_WRITE | FD_CLOSE);
	
	while(GetMessage(&Msg, NULL, 0, 0) > 0)
	{
		TranslateMessage(&Msg);
		DispatchMessage(&Msg);
	}
	return Msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch(msg)
	{
		case WM_CREATE:
			hMenu = CreateMenu();

			hSubMenu = CreatePopupMenu();
			AppendMenu(hSubMenu, MF_STRING, ID_FILE_LISTEN, "&Listen");
			AppendMenu(hSubMenu, MF_STRING, ID_FILE_SLISTEN, "&Stop Listening");
			AppendMenu(hSubMenu, MF_SEPARATOR, NULL, NULL);
			AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, "E&xit");
			AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&File");
			
			hSubMenu = CreatePopupMenu();
			AppendMenu(hSubMenu, MF_STRING, ID_ABOUT_HELP, "&About");
			AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&Help");
	
			SetMenu(hWnd, hMenu);	
		
			hEditIn = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL, 0, 0, 294, 500, hWnd, (HMENU)IDC_EDITI, GetModuleHandle(NULL), NULL);
		
			if(hEditIn == NULL)
			{
				MessageBox(hWnd, "Could not create edit box.", "Error", MB_OK | MB_ICONERROR);
			}
			 
			hEditOut = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL, 0, 500, 244, 55, hWnd, (HMENU)IDC_EDITO, GetModuleHandle(NULL), NULL);
		
			if(hEditOut == NULL)
			{
				MessageBox(hWnd, "Could not create edit box.", "Error", MB_OK | MB_ICONERROR);
			}
			
			hBtnSend = CreateWindowEx(WS_EX_CLIENTEDGE, "BUTTON", NULL, WS_CHILD | WS_VISIBLE, 244, 500, 50, 55, hWnd, (HMENU)IDC_BTNS, GetModuleHandle(NULL), NULL);
		
			if(hBtnSend == NULL)
			{
				MessageBox(hWnd, "Could not create button.", "Error", MB_OK | MB_ICONERROR);
			}
		break;
		
		case WM_SIZE:
    	   	SetDlgItemText(hWnd, IDC_BTNS, "Send");
    	break;
		
		case WM_CLOSE:
			DestroyWindow(hWnd);
		break;
		
		case WM_DESTROY:
			PostQuitMessage(0);
		break;
		
		case WM_COMMAND:
			switch(LOWORD(wParam))
			{
				case ID_FILE_LISTEN:
					if (listen(sListen, 1) == SOCKET_ERROR)
					{
						MessageBox(NULL, "Error in listening", "Error!", NULL);
						WSACleanup();
					}
				break;
				
				case ID_FILE_SLISTEN:
					SetDlgItemText(hWnd, IDC_EDITI, "Winsock Shut Down.");
				
					closesocket(sClient);
					closesocket(sListen);
					WSACleanup();
				break;
				
				case ID_FILE_EXIT:
					PostQuitMessage(0);
				break;
				
				case ID_ABOUT_HELP:
					MessageBox(NULL, "Programmer: Steven Merrick", "About Lithnet Chat", NULL);
				break;
				
				case IDC_BTNS:
					char buffer[256];
					memset(buffer, 0, sizeof(buffer)); // Clears the buffer.
					
					GetDlgItemText(hWnd, IDC_EDITO, buffer, sizeof(buffer));
					send(sClient, buffer, sizeof(buffer), 0);
					
					SetDlgItemText(hWnd, IDC_EDITO, "");
				break;
			}
		break;
		
		case SOCKET_READY:
			if (WSAGETSELECTERROR(lParam))
			{
				WSACleanup();
				return(0);
			}

		    switch (WSAGETSELECTEVENT(lParam))
		    {
				case FD_ACCEPT:
					sClient = accept(sListen, NULL, NULL);
			
					if (sClient == SOCKET_ERROR)
					{
						MessageBox(NULL, "Error in accepting", "Error!", NULL); // Cout an error message.
						WSACleanup(); // Shutdown Winsock
					}
					
					SetDlgItemText(hWnd, IDC_EDITI, "Connection recieved.");
				break;
				
				case FD_READ:
					char buffer[256];
					memset(buffer, 0, sizeof(buffer)); // Clears the buffer.
					
					if (recv(sClient, buffer, sizeof(buffer), 0) == SOCKET_ERROR)
					{
						MessageBox(NULL, "Error in recv()", "Error", NULL);
					}
					
					SetDlgItemText(hWnd, IDC_EDITI, buffer);
				break;
				
				case FD_CLOSE:
					SetDlgItemText(hWnd, IDC_EDITI, "Client disconnected.");
				break;
			}
		break;
				
		default:
			return DefWindowProc(hWnd, msg, wParam, lParam);
	}

	return(0);
}
Lithorien is offline   Reply With Quote
Old 12-30-2004, 12:11 PM   #11
I am me, who else?
 
Join Date: Oct 2002
Posts: 250
congrats! always feels good having working code I dont really have something contructive to say besides good luck, I always view coding as an adventure that can be frustrating but enjoyed immensely given the right environment.

Oh probably a nitpick more than anything is probably something which handles errors in the program, say you get a WSAGETSELECTERROR and it turns out to be something, it would be a good idea to handle it, and display it in some way to make it easy for the user to know whats happening (I know I don't do that nearly enough, but something to think on anyway).
dpro is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
winsock help Anubis208 C++ Programming 1 03-05-2008 07:46 AM


All times are GMT -6. The time now is 09:23 PM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0 RC2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22