problem with WM_SOCKET

I am writing a small game using network code. I have managed to let 2 players connect to the server, but after that it goes wrong.
The second player almost automatically quits. (Never the second one)
This happens when I run the the server once and the client app twice on my computer, but also when I run one server and one client, and another computer just the client app.

The servercode that generates the error is here :

//listening...accepting...connecting...
//so far so goed

printf("Starting Game!\n");

closesocket (s[0]);

char buffer[2];
sprintf (buffer,"%c%d",HL_STARTGAME,0);

error = send (s[1],buffer,2,0);
printf("error %4d\n", error);
if ((error==0)||(error==SOCKET_ERROR))
{
printf("Error: Player 1 quit!\n");
WSACleanup ();
return;
}

error = send (s[2],buffer,2,0);
printf("error %4d\n", error);

//here, 'error' has the value of -1
//as a consequence, a WSACleanup is performed.

if ((error==0)||(error==SOCKET_ERROR))
{
printf("Error: Player 2 quit!\n");
WSACleanup ();
return;
}

Does anyone have a clue why this error is generated ?
This is the client code. I left out my ip.

void game_init()
{
WSADATA w;
int error = WSAStartup (0x0202,&w);

if (error)
{
MessageBox (hWnd,"Error: You need WinSock 2.2!","Error",MB_OK);
PostQuitMessage (0);
return;
}
if (w.wVersion!=0x0202)
{
MessageBox (hWnd,"Error: Wrong WinSock version!","Error",MB_OK);
PostQuitMessage (0);
WSACleanup ();
return;
}

//no errors here

s = socket (AF_INET,SOCK_STREAM,0);

if (s == INVALID_SOCKET) {
printf("Error at socket(): %ld\n", WSAGetLastError());
WSACleanup();
return;
}

//no errors here either

//WSAAsyncSelect (s,hWnd,WM_SOCKET,(FD_CLOSE | FD_CONNECT | FD_READ));
//I disabled WSAASyncSelect because when I enable it,
//an error is generate in WndProc ( in the WM_SOCKET block)
//(see a bit further)

ip[0] = (char)***;
ip[1] = (char)***;
ip[2] = (char)***;
ip[3] = (char)***;

char a[16];
sprintf (a,"%d.%d.%d.%d",(int)ip[0],(int)ip[1],(int)ip[2],(int)ip[3]);

you.sin_family = AF_INET;
you.sin_port = htons (5555);
you.sin_addr.s_addr = inet_addr (a);

if (connect(s,(LPSOCKADDR)&you,sizeof(you))==SOCKET_ERROR)
{
if (WSAGetLastError()==WSAEWOULDBLOCK)
{
printf("wsaewouldblock error...\n");
Sleep (750);
connect(s,(LPSOCKADDR)&you,sizeof(you));
}break;

sprintf (txtbuffer,"Error: %d",WSAGetLastError());
MessageBox (hWnd,txtbuffer,"Error ",MB_OK);
}
return;
}

//here's the WM_SOCKET part from wndProc

case WM_SOCKET:
{
printf("wm_socket opgeroepen...");
if (WSAGETSELECTERROR(lParam))
{
sprintf (txtbuffer,"Error2: %d",WSAGetLastError());
MessageBox (hWnd,txtbuffer,"Error",MB_OK);
return 0;
}

switch (WSAGETSELECTEVENT(lParam))
{
case FD_READ:
//and so on...

Here, the MessageBox from the second clien gives an error which sais 'Error2: 0'
From the moment that the second cliend has had this error, the first client gets it too. The first one gets it too from the WM_SOCKET part.
I don't know why it does that

Has not using
WSAAsyncSelect (s,hWnd,WM_SOCKET,(FD_CLOSE | FD_CONNECT | FD_READ));
have anything to do with it maybe?

Does anyone have a clue ?

Thanks in advance.
[3784 byte] By [hannibar] at [2007-11-19 1:36:10]
# 1 Re: problem with WM_SOCKET
Buffer-overrun:
char buffer[2];
sprintf (buffer,"%c%d",HL_STARTGAME,0);This bug may cause all kinds of problems. The minimum size on 'buffer' should be 3 (with current values).

Are both programs (client and server) written as Windows programs (ie. WinMain and WinProc functions)? The reason I ask you this is because you're using blocking socket calls and these can/will block the message pump (not good).
j0nas at 2007-11-9 13:47:56 >
# 2 Re: problem with WM_SOCKET
Are both programs (client and server) written as Windows programs (ie. WinMain and WinProc functions)? The reason I ask you this is because you're using blocking socket calls and these can/will block the message pump (not good).The server program is written as a windows console app. (no WinMain and WndProc)
The client program is written as a windows app. (WinMain and WndProc)

How can I solve the blocking issue ?
hannibar at 2007-11-9 13:48:57 >
# 3 Re: problem with WM_SOCKET
How can I solve the blocking issue ?You can use threads that handle clients on a one to one basis. i.e., one thread per client, till that client goes away.
Mathew Joy at 2007-11-9 13:49:56 >
# 4 Re: problem with WM_SOCKET
Sorry for the newbish question about that, but could you give a small example, or some semi-code to show what you mean with that?

Thanks for the answer
hannibar at 2007-11-9 13:51:02 >
# 5 Re: problem with WM_SOCKET
The code sequence till accept() in the server is the same. The rest may look like this.

// ...
while ( TRUE )
{
cliSock = accept( srvSock, // the socket that is placed in a listening state
NULL, // struct that holds the address of the peer [optional]
NULL ); // the struct len [optional]

if ( cliSock == INVALID_SOCKET )
{
// handle the error using WSAGetLastError()
}

// spawing each thread for a connected client
//
hThread = ( HANDLE ) _beginthreadex( NULL, // security
0, // stack size (0 for default)
WorkerThread, // the thread routine
( PVOID )cliSock, // the argument (here we are sending the connected socket)
0, // state flag (0 for running)
( PUINT )&dwThreadId ); // the threadID

if ( ! hThread )
{
// handle the error using GetLastError()
}
else
CloseHandle( hThread ); // Closing the handle since we are not referencing it
}
}

/*
The worker thread that is spawned as soon as the connection is accepted.
This thread handles the client till the connection is gracefully closed.
*/
unsigned _stdcall WorkerThread ( LPVOID pArgs )
{

SOCKET cliSock = ( SOCKET ) pArgs;
CHAR RecvBuf[BUFSIZE];

while ( TRUE )
{
// call recv() and check the return value

// call send() and check the return value
}
}Hope you understand what the code does. :thumb:
Mathew Joy at 2007-11-9 13:52:01 >
# 6 Re: problem with WM_SOCKET
/*
The worker thread that is spawned as soon as the connection is accepted.
This thread handles the client till the connection is gracefully closed.
*/
unsigned _stdcall WorkerThread ( LPVOID pArgs )
{

SOCKET cliSock = ( SOCKET ) pArgs;
CHAR RecvBuf[BUFSIZE];

while ( TRUE )
{
// call recv() and check the return value

// call send() and check the return value
}
}

did you mean "__stdcall" or is _stdcall also correct? :confused:
NoHero at 2007-11-9 13:53:01 >
# 7 Re: problem with WM_SOCKET
Thanks alot for the very clear explanation.
Hope you understand what the code does.Yes, I understand what it does perfectly. It's even simpler than I expected to be honest. I thought threads would be overcomplicated, but it looks quite ok to me now :)

Once again thanks
hannibar at 2007-11-9 13:54:06 >
# 8 Re: problem with WM_SOCKET
I have a question about the threads and sockets.
I have rewritten the server code to support threads. The problem however is that I don't know how to send() to the other clients. In the WorkerThread, only one socket is known, not the other one(s).
How could I solve this ?

Thanks in advance.
hannibar at 2007-11-9 13:55:09 >
# 9 Re: problem with WM_SOCKET
Another thing : When using the threading it still doesn't work.
hannibar at 2007-11-9 13:56:07 >
# 10 Re: problem with WM_SOCKET
The problem however is that I don't know how to send() to the other clients. In the WorkerThread, only one socket is known, not the other one(s).
How could I solve this ?One design is as follows. The interaction is between the server and the clients or the server and the worker threads. So if one thread wan'ts to send message to another thread, it notifies the server and the server in-turn notifies the appropriate worker thread. This can be implemented using a queue. Depending on the no. of threads or usage it could be a global queue or a one queue per thread.

Another thing : When using the threading it still doesn't work.I'm sorry, I don't understand by what you mean.
Mathew Joy at 2007-11-9 13:57:08 >
# 11 Re: problem with WM_SOCKET
I mean that when I use threading, the originla problem still isn't solved. I still get the same error described in the first post.

What I actually want to do with the program is this : I want to make a simple (very simple) multiplayer game between two people. It should be a windows32 application (not a console app).

Maybe it would be best if someone could point me to an example program. Unfortunatley, google didn't get good results. I did find a few tutorials, but they don't fit my needs.
hannibar at 2007-11-9 13:58:07 >