Sign in to follow this  
brandonman

Getting Started With MUD's

Recommended Posts

OK, I asked this question when I first started programming, at age 11... I can't stand reading my posts from then ;) Anyways, I have played some MUD's now and would like to get into some Networking. I'm just about to market my current Opengl 2D game, just building hype with an ARG (Was in Game Informer, to lazy to dig up the issue number, just a form of media. A game spanning multiple medias basically) I'm working on a run 'n gun right now. Just sharing my experience. I would like to get into some networking, as that seems to be the industry's future. So I figure I'll start with a MUD. I've done a simple little program with a tutorial that connects to a website and dumps you the header. I didn't really understand it that well... I would like to try Beeje's, but I am on windows, so I would be using winsock 2. I don't really want to use cygwin and use linux stuff instead of winsock. What would you suggest? Maybe point me on a path, an article to read, maybe some stuff to try and do on my own, ideas for practice programs to try out things I learn, etc. So, any tips? Thanks in advance.

Share this post


Link to post
Share on other sites
The FAQ has some links to Winsock tutorials :)

This one, for instance.


MUDs are fairly easy networking-wise, in that they pretty much just push ASCII strings back and forth (you can use any telnet client to play a MUD, for example). In other words, the clients are just dumb terminals and everything happens serverside.

After you've got the basic listening stuff set up (see the tutorial, and for gods sake don't create a new thread per client for this kind of server :P ), you just need to read the input from each one until you hit a newline (which will separate each command sent from the telnet client) and parse it however you want.


EDIT: Should also mention that, while it may be a bit much to parse, there's a lot of open source MUD servers you can download and look at. Good place to start reading about that in general: http://en.wikipedia.org/wiki/LPMud

[Edited by - Vinterstum on March 4, 2008 12:27:25 PM]

Share this post


Link to post
Share on other sites
thanks vintersum. I am going to read that winsock article you linked to. I've skimmed that before but never really read it. I'll let everyone know how this all works out, when it happens. ;) (Us programmers and procrastinating, heh)

Share this post


Link to post
Share on other sites
I don't want to make another thread, as this is probably something trivial. I read the winsock 2 for games thing thoroughly, and even understood everything :D
Now I went and I took all the functions and such and put them into a main function, and i'm getting a lot of errors. I even get the same errors when I run the source code that is in the zip. I am using Dev C++.
Here's the code:

#include <iostream>
#include <string>
#include <sstream>
#define MAX_CLIENTS 5; // just used for clearness
#define WIN32_MEAN_AND_LEAN
#include <winsock2.h>
#include <windows.h>

using namespace std;


int number_of_clients = 0;
int main ()
{
// Must be done at the beginning of every WinSock program
WSADATA w; // used to store information about WinSock version
int error = WSAStartup (0x0202, &w); // Fill in w

if (error)
{ // there was an error
return 1;
}
if (w.wVersion != 0x0202)
{ // wrong WinSock version!
WSACleanup (); // unload ws2_32.dll
return 1;
}

SOCKET s = socket (AF_INET, SOCK_STREAM, 0); // Create socket

// Note that you should only bind server sockets, not client sockets
// SOCKET s is a valid socket
// WSAStartup has been called

sockaddr_in addr; // the address structure for a TCP socket

addr.sin_family = AF_INET; // Address family Internet
addr.sin_port = htons (5001); // Assign port 5001 to this socket
addr.sin_addr.s_addr = htonl (INADDR_ANY); // No destination
if (bind(s, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR)
{ // error
WSACleanup (); // unload WinSock
return 1; // quit
}

// WSAStartup () has been called
// SOCKET s is valid
// s has been bound to a port using sockaddr_in sock
if (listen(s,5)==SOCKET_ERROR)
{ // error! unable to listen
WSACleanup ();
return false;
}

// listening…


// WSAStartup () has been called
// SOCKET s is valid
// s has been bound to a port using sockaddr_in sock
// s is listening




SOCKET client[5]; // socket handles to clients
sockaddr client_sock[MAX_CLIENTS]; // info on client sockets

while (number_of_clients < MAX_CLIENTS) // let MAX_CLIENTS connect
{
client[number_of_clients] = // accept a connection
accept (s, client_sock[number_of_clients], &addr_size);
if (client[number_of_clients] == INVALID_SOCKET)
{ // error accepting connection
WSACleanup ();
return false;
}
else
{ // client connected successfully
// start a thread that will communicate with client
startThread (client[number_of_clients]);
number_of_clients++;
}
}


// SOCKET s is initialized
char buffer[11]; // buffer that is 11 characters big
sprintf (buffer, "Whatever…");

send (s, buffer, sizeof(buffer), 0);


shutdown (s, SD_SEND); // s cannot send anymore

// you should check to see if any last data has arrived here

closesocket (s); // close

return 0;
}




now here's the compile log:

Compiler: Default compiler
Building Makefile: "C:\Dev-Cpp\MUD project\Makefile.win"
Executing make...
make.exe -f "C:\Dev-Cpp\MUD project\Makefile.win" all
g++.exe -D__DEBUG__ -c main.cpp -o main.o -I"lib/gcc/mingw32/3.4.2/include" -I"include/c++/3.4.2/backward" -I"include/c++/3.4.2/mingw32" -I"include/c++/3.4.2" -I"include" -g3

main.cpp: In function `int main()':
main.cpp:67: error: expected primary-expression before "client_sock"
main.cpp:67: error: expected `;' before "client_sock"
main.cpp:67: error: expected primary-expression before ']' token
main.cpp:67: error: expected `;' before ']' token
main.cpp:69: error: expected `)' before ';' token
main.cpp:69: error: expected primary-expression before ')' token
main.cpp:69: error: expected `;' before ')' token

make.exe: *** [main.o] Error 1

Execution terminated





Normally I get all these errors when I forget to close up a loop with } but I don't see any open loops anywhere.

Share this post


Link to post
Share on other sites
Look at the definition of MAX_CLIENTS. You likely don't want a semicolon there.

I'm trying to move this follow-up question into General Programming as it just has to do with getting code compiling, not with networking. We'll see if I have the forum-fu to manage...

Share this post


Link to post
Share on other sites

Compiler: Default compiler
Building Makefile: "C:\Dev-Cpp\MUD project\Makefile.win"
Executing make...
make.exe -f "C:\Dev-Cpp\MUD project\Makefile.win" all
g++.exe -D__DEBUG__ -c main.cpp -o main.o -I"lib/gcc/mingw32/3.4.2/include" -I"include/c++/3.4.2/backward" -I"include/c++/3.4.2/mingw32" -I"include/c++/3.4.2" -I"include" -g3

main.cpp: In function `int main()':
main.cpp:72: error: `addr_size' undeclared (first use this function)
main.cpp:72: error: (Each undeclared identifier is reported only once for each function it appears in.)

main.cpp:81: error: `startThread' undeclared (first use this function)

make.exe: *** [main.o] Error 1

Execution terminated





#include <iostream>
#include <string>
#include <sstream>
#define MAX_CLIENTS 5 // just used for clearness
#define WIN32_MEAN_AND_LEAN
#include <winsock2.h>
#include <windows.h>

using namespace std;


int number_of_clients = 0;
int main ()
{
// Must be done at the beginning of every WinSock program
WSADATA w; // used to store information about WinSock version
int error = WSAStartup (0x0202, &w); // Fill in w

if (error)
{ // there was an error
return 1;
}
if (w.wVersion != 0x0202)
{ // wrong WinSock version!
WSACleanup (); // unload ws2_32.dll
return 1;
}

SOCKET s = socket (AF_INET, SOCK_STREAM, 0); // Create socket

// Note that you should only bind server sockets, not client sockets
// SOCKET s is a valid socket
// WSAStartup has been called

sockaddr_in addr; // the address structure for a TCP socket

addr.sin_family = AF_INET; // Address family Internet
addr.sin_port = htons (5001); // Assign port 5001 to this socket
addr.sin_addr.s_addr = htonl (INADDR_ANY); // No destination
if (bind(s, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR)
{ // error
WSACleanup (); // unload WinSock
return 1; // quit
}

// WSAStartup () has been called
// SOCKET s is valid
// s has been bound to a port using sockaddr_in sock
if (listen(s,5)==SOCKET_ERROR)
{ // error! unable to listen
WSACleanup ();
return false;
}

// listening…


// WSAStartup () has been called
// SOCKET s is valid
// s has been bound to a port using sockaddr_in sock
// s is listening




SOCKET client[5]; // socket handles to clients
sockaddr client_sock[MAX_CLIENTS]; // info on client sockets

while (number_of_clients < MAX_CLIENTS) // let MAX_CLIENTS connect
{
client[number_of_clients] = // accept a connection
accept (s, client_sock[number_of_clients], &addr_size);
if (client[number_of_clients] == INVALID_SOCKET)
{ // error accepting connection
WSACleanup ();
return false;
}
else
{ // client connected successfully
// start a thread that will communicate with client
startThread (client[number_of_clients]);
number_of_clients++;
}
}


// SOCKET s is initialized
char buffer[11]; // buffer that is 11 characters big
sprintf (buffer, "Whatever…");

send (s, buffer, sizeof(buffer), 0);


shutdown (s, SD_SEND); // s cannot send anymore

// you should check to see if any last data has arrived here

closesocket (s); // close

return 0;
}



STILL no joy. Any ideas? thanks.
EDIT: Did some searching and got the addr_size working. I can't get the startThread error though. Any ideas on that? Thanks for all the help

Share this post


Link to post
Share on other sites
Note that you haven't declared addr_size anywhere before you start to use it.

I suggest you start learning C/C++ programming before you start trying to create networked code. It's clear that your lack of C++ experience is getting in the way of the networking part.

Share this post


Link to post
Share on other sites
On a scale 1-5 as far as C/C++ skills go for me, I'd rate myself a 3.5. I never got into real advanced stuff like pointers or polymorphism, and such. I'd work more with pointers but I don't understand what they do. Anyways, I realized I forgot to make the int for the addr_size, I am on the thread thing. I'm not sure what this startThread function is, so I can't do any defines or ints, since it's a function... So, does anyone have any experience with this startThread?

Share this post


Link to post
Share on other sites
Quote:
Original post by brandonman
On a scale 1-5 as far as C/C++ skills go for me, I'd rate myself a 3.5. I never got into real advanced stuff like pointers or polymorphism, and such. I'd work more with pointers but I don't understand what they do. Anyways, I realized I forgot to make the int for the addr_size, I am on the thread thing. I'm not sure what this startThread function is, so I can't do any defines or ints, since it's a function... So, does anyone have any experience with this startThread?

Ah, this isn't a problem with your C/C++ skills my son (which are obviously not to blame -- one cannot be expected to understand such high-level concepts like pointers), but rather, with your copy-pasting skills. When you copied that code from the original source, you neglected to copy it completely! You forgot to copy the startThread function from that source.

I'd recommend using Ctrl-A next time to make sure you get everything.

Share this post


Link to post
Share on other sites
You've obviously copied the code from somewhere (I haven't read a lot of the thread to see if that was mentioned), but the fact is that startThread is a user defined function, it is likely not defined in any library shipped with the compiler. Winsock coding can be tricky at times, and you have to be comfortable with pointers in addition to knowing C or C++. I could sit here and answer your question by giving a working solution but then you'd keep coming back with more problems where it'd be in your best interest to get to the basics and learn the language well enough to handle some of the useful things available like the winsock library. Please heed that advice, it's not meant to belittle.

Share this post


Link to post
Share on other sites
I did use some copy/paste, but I read through everything and such, and also in the article's source, the startThread function is not defined anywhere anyways. I haven't found it with google/gamedev searching. So, please stop flaming me, and help me out, thanks a ton.

Share this post


Link to post
Share on other sites
Quote:
Original post by brandonman
I did use some copy/paste, but I read through everything and such, and also in the article's source, the startThread function is not defined anywhere anyways. I haven't found it with google/gamedev searching. So, please stop flaming me, and help me out, thanks a ton.

The tutorial you used uses startThread as pseudocode for a CreateThread wrapper. Doing sockets that way (with a thread for each client) is a complete waste of resources.

I'd recommend re-reading the article, then using a select-based approach to handling connections (ie, asynchronous sockets).

Share this post


Link to post
Share on other sites
Not to be a noob, but where would I splice the select() function into my code, and how would I do it? Hopefully the last question.

Share this post


Link to post
Share on other sites
To be brutally honest, if you think pointers is an advanced part of C++, you're not ready for this (it's absolutely essential).

I'd suggest either 1) learn C++ more deeply before broaching something like this, or 2) consider picking up and using C# instead (it'll be much, much easier to get into the more advanced concepts like networking and threading using C#, rather than C++ which is rather clunky and takes a long time to get comfortable with).

Share this post


Link to post
Share on other sites
Quote:
On a scale 1-5 as far as C/C++ skills go for me, I'd rate myself a 3.5


If you don't know pointers or polymorphism, then you should rate yourself 1 on a scale from 1 to 5.

Also read question 0 in the Forum FAQ as it will help you a lot with this and other problems.

Share this post


Link to post
Share on other sites
I don't consider pointers "Advanced" really, I should have rephrased that post, I just never could exactly get what their use was. I mean, it returns the address location of a variable it points to. I don't see why you can't just use that variable. Back on track - where exactly should I splice the select() function into my code?

Share this post


Link to post
Share on other sites
You will not make more progress until you learn the language you're trying to express yourself in. Pointers are the only way you can use the heap, and using the heap is the only way you can have a dynamic memory store.

Share this post


Link to post
Share on other sites
Guest
This topic is now closed to further replies.
Sign in to follow this