Valhalla Legends Forums Archive | C/C++ Programming | Creating A Server

AuthorMessageTime
Final
Hey Guys whats up Ive been working on making a server for a game a friend of mine and me are doing and im doing the server but I have a problem how can I make it hold more than one user in the server.
Its using winsock asynchronous.
He gave me an example in vb but How does Index Work?
All I want to know is how to accept more than 1 user and keep the connections going?
March 11, 2006, 7:31 PM
Yegg
[quote author=Final link=topic=14492.msg148140#msg148140 date=1142105474]
Hey Guys whats up Ive been working on making a server for a game a friend of mine and me are doing and im doing the server but I have a problem how can I make it hold more than one user in the server.
Its using winsock asynchronous.
He gave me an example in vb but How does Index Work?
All I want to know is how to accept more than 1 user and keep the connections going?
[/quote]

Well, have you got any code written so far? And what is this "Index" you speak of?
March 11, 2006, 8:08 PM
Kp
Don't close the socket of the first user when you accept a connection from the second user!
March 11, 2006, 8:10 PM
Final
Ok let me show you what im working with.
[code]
            case WM_SOCKET:
    {
if (WSAGETSELECTERROR(lparam))
{ // error!
PostQuitMessage (0);
}
switch (WSAGETSELECTEVENT(lparam))
{
            case FD_READ:
            {
             
              int ncmdshow;
              ZeroMemory(packetbuffer, 256);
              ncmdshow = recv(s, packetbuffer, 256, 0);
              //parse();
              //char* string=packet+intwereitstarts;
              ncmdshow = send(wParam, packetbuffer, strlen(packetbuffer), 0);
              SendMessage(hedit_2, WS_VSCROLL, SB_LINEDOWN, 0);
            } break;
            case FD_WRITE:
            {
            } break;
            case FD_ACCEPT:
              {
              int ncmdshow;
              char buffer[256];
              char strTem[5000];
              char sa[MAX_PATH];
              char* sp="\n";
            s=accept(wParam,NULL, NULL);
              cout<<wParam<<endl;
              GetWindowText(hedit_2, strTem, 5000);
              sprintf(sa, "%s%s%s", strTem,sp,"A User has Connected to the Server");
              SetWindowText(hedit_2,sa);
              ncmdshow = send(wParam, sa, strlen(sa), 0);
              SendMessage(hedit_2, WS_VSCROLL, SB_LINEDOWN, 0);
                } break;
                case FD_CLOSE:
                {
                char strTem[5000];
              char sa[MAX_PATH];
              char* sp="\n";
              GetWindowText(hedit_2, strTem, 5000);
              sprintf(sa, "%s%s%s", strTem,sp,"A User has disconnected to the Server");
              SetWindowText(hedit_2,sa);
              SendMessage(hedit_2, EM_SCROLL, SB_LINEDOWN, 0);
                  } break;
}
} break;
//Socket End//
[/code]
March 12, 2006, 10:02 AM
FrOzeN
[quote author=Final link=topic=14492.msg148140#msg148140 date=1142105474]
He gave me an example in vb but How does Index Work?
[/quote]
Don't try comparing the example I gave you in VB6 to C++. Index was the current item in the control array of Winsock.

So whatever the varible your using to create the socket, make it an array so you can setup multiple connections with ease of working with the varibles.

Other than that C++ is pretty obsolete to me atm, so I can't really follow up any more questions that arise based on arrays in C++ etc..
March 12, 2006, 10:10 AM
Final
Could someone still help me out on it being able to handle more than one connection and keeping it on or take it out if the person leaves.
March 12, 2006, 11:14 AM
Kp
[quote author=Final link=topic=14492.msg148189#msg148189 date=1142157757]
Ok let me show you what im working with.[/quote]

Since you've already indicated you're new to this, I won't hold the following code against you.  That said, it's really bad code. :)

[quote author=Final link=topic=14492.msg148189#msg148189 date=1142157757][code]
            case WM_SOCKET:
    {
if (WSAGETSELECTERROR(lparam))
{ // error!
PostQuitMessage (0);
}
switch (WSAGETSELECTEVENT(lparam))
{
            case FD_READ:
            {
             
              int ncmdshow;
              ZeroMemory(packetbuffer, 256);[/code][/quote]

First mistake: don't use magic numbers.  From context, I'm guessing that 256 is the number of bytes in packetbuffer (i.e. that you did [u]char packetbuffer[256];[/u] somewhere that didn't get pasted).  It's better to specify that you want the compiler to compute the size automatically.  Then, if it ever changes, the compiler automatically uses the new value when you rebuild.  Use [u]ZeroMemory(packetbuffer, sizeof(packetbuffer));[/u].

[quote author=Final link=topic=14492.msg148189#msg148189 date=1142157757][code]
              ncmdshow = recv(s, packetbuffer, 256, 0);[/code][/quote]

Ditto the magic number issue for the recv(2) call.  You're not checking whether the recv(2) failed (or returned that the connection closed (both of which may be a non-issue for the particular type of event-driven I/O you're doing, but it's worth keeping in mind)).  Also, calling the recv(2) result ncmdshow looks a bit weird.

[quote author=Final link=topic=14492.msg148189#msg148189 date=1142157757][code]
              //parse();
              //char* string=packet+intwereitstarts;[/code][/quote]

It's better not to name variables string, since then you can't use STL's std::string without a fully qualified name.  This is just a style issue. :)

[quote author=Final link=topic=14492.msg148189#msg148189 date=1142157757][code]
              ncmdshow = send(wParam, packetbuffer, strlen(packetbuffer), 0);[/code][/quote]

You're assuming that the client will send a null-terminated message.  If it doesn't, that strlen will walk off the end of packetbuffer looking for a null.  If you're just trying to echo the result back, pass the amount received as the length parameter of send(2).

[quote author=Final link=topic=14492.msg148189#msg148189 date=1142157757][code]
              SendMessage(hedit_2, WS_VSCROLL, SB_LINEDOWN, 0);[/code][/quote]

WS_VSCROLL is a style, not a message.  If the SendMessage call has any effect at all, it probably won't be what you want.

[quote author=Final link=topic=14492.msg148189#msg148189 date=1142157757][code]
            } break;
            case FD_WRITE:
            {
            } break;
            case FD_ACCEPT:
              {
              int ncmdshow;
              char buffer[256];
              char strTem[5000];
              char sa[MAX_PATH];
              char* sp="\n";
            s=accept(wParam,NULL, NULL);
              cout<<wParam<<endl;
              GetWindowText(hedit_2, strTem, 5000);[/code][/quote]

Unicode cleanliness issue: you're using GetWindowText, which takes a TCHAR *, with a char[] argument.  This will work in MBCS mode, but breaks in Unicode mode.  Use GetWindowTextA or switch strTem to be a TCHAR[] array.  You may need to include <tchar.h> for the latter change.  Also, magic numbers again. :)

Also, buffer is unused.

[quote author=Final link=topic=14492.msg148189#msg148189 date=1142157757][code]
              sprintf(sa, "%s%s%s", strTem,sp,"A User has Connected to the Server");[/code][/quote]

Looks a little weird, is wasteful, and badly susceptible to a buffer overflow.  MAX_PATH is only 260 on Windows, so you can easily overrun sa and have bad things happen.  The canonical workaround for the lack of good output devices on Windows is to programmatically select a zero-length region anchored at the end of the control, then replace its contents with the message you want to add.  See EM_SETSEL and EM_REPLACESEL.

Consider using _snprintf to get bounds-limited formatting.  Note that Microsoft's _snprintf stupidly doesn't null-terminate its output like GNU libc's snprintf does.  So, you'll see a lot of constructs of the form:

[code]
_snprintf(buf, sizeof(buf) - 1, "format_string", <args>);
buf[(sizeof(buf) / sizeof(buf[0])) - 1] = 0;
[/code]

[quote author=Final link=topic=14492.msg148189#msg148189 date=1142157757][code]
              SetWindowText(hedit_2,sa);[/code][/quote]

Unicode cleanliness again.  Consider SetWindowTextA if you left sa as a char[].

[quote author=Final link=topic=14492.msg148189#msg148189 date=1142157757][code]
              ncmdshow = send(wParam, sa, strlen(sa), 0);[/code][/quote]

Do you really intend to be sending back the entire contents to every new user?

[quote author=Final link=topic=14492.msg148189#msg148189 date=1142157757][code]
              SendMessage(hedit_2, WS_VSCROLL, SB_LINEDOWN, 0);[/code][/quote]

Again, WS_VSCROLL.

[quote author=Final link=topic=14492.msg148189#msg148189 date=1142157757][code]
                } break;
                case FD_CLOSE:
                {
                char strTem[5000];
              char sa[MAX_PATH];
              char* sp="\n";
              GetWindowText(hedit_2, strTem, 5000);
              sprintf(sa, "%s%s%s", strTem,sp,"A User has disconnected to the Server");
              SetWindowText(hedit_2,sa);[/code][/quote]

Same issues as in FD_READ.
March 12, 2006, 4:57 PM
Final
Thanks for that much.
But After A while of talking with frozen and reading some resource I managed to hold connections now my problem is how do i send a message to all my users that are connected.
There all under a socket array.
But for some reason I cant send anything to them? could someone help me out.
March 13, 2006, 1:46 AM
rabbit
Loop through the array and call send() on each with the data you want to send.
March 13, 2006, 3:50 AM
Final
I already tried that.
unless Im Accepting it wrong

this is how I was accepting it.
[code]
array[#] '=' accept(stuff,NULL,NULL);
[/code]


What am I doing wrong.
March 13, 2006, 6:35 AM
FrOzeN
Huh? You just said you were able to hold your connections. When connections arrive on the port your listening to you recieve a request in which you either accept or decline the connection.

If you haven't got past the stage of accepting the connections properally. Then the statement "I managed to hold connections now" is very far off. Just trying to point this out, because the terminology your using is probably making it bit confusing for the others to understand where your up to.

I can't exactly help with any of the coding, I can only provide the pseudo method in which it has to be done.
March 13, 2006, 6:41 AM
Final
Sorry About that what I mean is holding Connection Info To play with. To send information to everyone but nevermind I finally got it done I had done something wrong witht the loop but i fixed it and it works fine now. Thankyou everyone for all the help that you gave me I really appreciate it all.
March 13, 2006, 7:23 AM

Search