First off, I am very inexperienced with network programming, but I thought I'd try my hand with asynchronous sockets. So, after reading some of this tutorial, I made a program that should be able to connect or wait for a connection. So I made a network class, and simply set it to connect to my local ip address if a button is pressed, or set to listen mode if the other button is pressed.
I can tell something is working, because I receive a FD_ACCEPT message on the instance I set to listen, but then my program never seems to reach any code after I call accept():
My window proc:
Code:
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) /* handle the messages */
{
case WM_CREATE:
CreateWindowEx(0, //more or 'extended' styles
TEXT("BUTTON"), //'class' of control to create
TEXT("Connect"), //the control caption
WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON, //control style: how it looks
10, //control position: left
10, //control position: top
100, //control width
20, //control height
hwnd, //parent window handle
(HMENU)IDC_CONNECT, //control's ID
g_hInst, //application instance
NULL);
CreateWindowEx(0, //more or 'extended' styles
TEXT("BUTTON"), //'class' of control to create
TEXT("Wait"), //the control caption
WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON, //control style: how it looks
120, //control position: left
10, //control position: top
100, //control width
20, //control height
hwnd, //parent window handle
(HMENU)IDC_SERVER, //control's ID
g_hInst, //application instance
NULL);
break;
case WM_WSAASYNC:
// what word?
switch(WSAGETSELECTEVENT(lParam))
{
case FD_ACCEPT:
MessageBox(NULL,"Connection request received","Alert!",MB_OK); //this comes up
// check for an error
if (WSAGETSELECTERROR(lParam))
return(FALSE);
// process message
try
{
netwkobj.Accept();
}
catch (const NetErr& error)
{
MessageBox(NULL,error.what(),"Network Error",MB_OK|MB_ICONEXCLAMATION);
}
return(0);
break;
case FD_READ:
//receiving data
break;
case FD_WRITE:
//..
break;
case FD_CONNECT:
//server got our connect message
MessageBox(NULL,"Connect request accepted","Alert!",MB_OK); // this never comes up
break;
case FD_CLOSE:
//connection closed
PostQuitMessage(0); //just quit for now...i guess
break;
}
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDC_CONNECT: //button pressed: try to connect to a server
try
{
netwkobj.Init(hwnd,false);
netwkobj.Connect("192.168.2.15");
}
catch (const NetErr& error)
{
MessageBox(NULL,error.what(),"Network Error!",MB_OK|MB_ICONEXCLAMATION);
}
//MessageBox(NULL,"Connected","OK",MB_OK);
break;
case IDC_SERVER:
try
{
netwkobj.Init(hwnd,true); //move this to when we try to join or host a game in a menu
}
catch (const NetErr& error)
{
MessageBox(NULL,error.what(),"Network Error!",MB_OK|MB_ICONEXCLAMATION);
}
// MessageBox(NULL,"Listening...","OK",MB_OK);
break;
}
break;
case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
Member functions:
Code:
//network class member fcns
Network::Network()
{
hSocket = INVALID_SOCKET;
numclients=0;
}
void Network::Init(HWND hwnd, bool isserver)
{
init = true;
WSADATA wsaData;
if (WSAStartup(MAKEWORD(REQ_WINSOCK_VER,0), &wsaData)==0) //start winsock
{
// Check if major version is at least REQ_WINSOCK_VER
if (LOBYTE(wsaData.wVersion) < REQ_WINSOCK_VER)
{
throw NetErr("Required Winsock Version not met!");
}
}
else
throw NetErr("Error starting Winsock!");
// create and test the socket
hSocket = socket(AF_INET, SOCK_STREAM, 0);
if (hSocket == INVALID_SOCKET)
throw NetErr("INVALID_SOCKET");
// make the socket asynchronous and notify of read, write, connect and close events
// this is the client socket
if (!isserver)
{
WSAAsyncSelect(hSocket, hwnd, WM_WSAASYNC, FD_WRITE | FD_CONNECT |
FD_READ | FD_CLOSE); //set up asynchronous sockets
//request WRITE, READ, CONNECT, and CLOSE messages be sent
server=false;
}
// make the socket asynchronous and notify of read, write, accept and close events
// this is the server socket
else
{
//is this the right order? (set to listen before call to WSAAsyncSelect()?
sockaddr_in sockAddr = {0};
SetServerSockAddr(&sockAddr, SERVER_PORT);
if (bind(hSocket, reinterpret_cast<sockaddr*>(&sockAddr), sizeof(sockAddr))!=0)
throw NetErr("Could not bind socket.");
if (listen(hSocket, SOMAXCONN)!=0) //set socket to listen for incoming data
throw NetErr("Could not put socket into listening mode.");
WSAAsyncSelect(hSocket, hwnd, WM_WSAASYNC, FD_READ | FD_WRITE |
FD_ACCEPT | FD_CLOSE); //again, async sockets
server=true;
}
}
void Network::Connect(const char* servIp)
{
if (!init)
throw NetErr("Network not initialized!");
sockaddr_in sockAddr = {0};
FillSockAddrDot(&sockAddr, servIp, SERVER_PORT);
if ((hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
throw NetErr("Could not create socket.");
// Connect to server
if (connect(hSocket, reinterpret_cast<sockaddr*>(&sockAddr), sizeof(sockAddr))!=0)
throw NetErr("Could not connect.");
}
void Network::Accept()
{
if (!init)
throw NetErr("Network not initialized!");
int clientSockSize = sizeof(client_addr);
client_sock[0] = accept(hSocket,reinterpret_cast<sockaddr*>(&client_addr), &clientSockSize);
//I never get an exception thrown, and if I put a messagebox here
//it never comes up
if (client_sock[numclients]==INVALID_SOCKET)
throw NetErr("Could not accept incoming connection");
numclients++;
}
As I said, it seems to be working up to that point (I get a "could not connect" exception if I try to connect without setting another instance to wait, and if I set one to wait, when I click "connect" the other instance receives an FD_ACCEPT message)
Hopefully I'm just doing something stupid, since this is my first try with asynchronous sockets.
Edit: Boy, I feel stupid. I guess WSAGETSELECTERROR is telling me there's an error. Somehow I just glanced over that line. Should've put some kind of notification there. Now I just gotta figure out what the error means...
Edit2: MSDN doesn't have any error codes listed for the FD_ACCEPT message, and it returns error code 8...If I just continue like there's no problem, accept finished like there isn't a problem, but my client doesn't receive an FD_CONNECT message.
Edit3: Yes, another edit. Ok so now I realize that there aren't actually any error (stupid tutorial told me wrong) But I still don't receive a FD_CONNECT message...I think I'll take a break on this now...