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