Where do I initialize Winsock and catch messages for it?

This is a discussion on Where do I initialize Winsock and catch messages for it? within the Windows Programming forums, part of the Platform Specific Boards category; I am writing a piece of code for asynchronious chatting (If you saw my last thread on this, it's the ...

  1. #1
    Registered User
    Join Date
    Aug 2004
    Location
    San Diego, CA
    Posts
    313

    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);
    }

  2. #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 02:27 PM.

  3. #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.

  4. #4
    Registered User
    Join Date
    Aug 2004
    Location
    San Diego, CA
    Posts
    313
    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);
    }

  5. #5
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,246
    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.

  6. #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.

  7. #7
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,246
    dpro >> He moved that code to menu event handler.

  8. #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 01:43 PM.

  9. #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.

  10. #10
    Registered User
    Join Date
    Aug 2004
    Location
    San Diego, CA
    Posts
    313
    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);
    }

  11. #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).

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. winsock help
    By Anubis208 in forum C++ Programming
    Replies: 1
    Last Post: 03-05-2008, 06:46 AM

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