Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Anyone made a small multiplayer (network) game?

This thread is locked; no one can reply to it. rss feed Print
 1   2 
Anyone made a small multiplayer (network) game?
TeaRDoWN
Member #8,518
April 2007
avatar

I am going to add a multiplayer feature in my latest game but cannot find a good example of how to get any socket programming working with Winsock and Allegro 4 in Windows (MSVC).

Is there anyone who have made a small game or program and is willing to show it here or send it to me? Even better if it is (fairly) simple to understand and just shows what is needed to include, link to and basically how to code it to get it to work.

All help would make me go from :'( to ;D

Elias
Member #358
May 2000

My advice would be to not use sockets directly but something like this: http://enet.bespin.org/

Sockets are not hard either, but using a wrapper like this simply saves you a few days of working out details already solved there.

--
"Either help out or stop whining" - Evert

AMCerasoli
Member #11,955
May 2010
avatar

Wow that library is incredible easy to build!!! It has a MSVC project file and a Code::Block project file... What you have to do is just open it and compile it...

It's incredible how ENet events are so similar to Allegro events. I also was looking for a networking library I think this is great.

Edit: I have just found an example, I haven't read it but supposedly shows how to create a chat, (Using ENet)

I was looking around for some example programs that use enet
but like others I couldn't find one. So I tried to make one myself.

This is a simple chat program. Multiple clients can join the server
and write messages. Messages will be received by all clients
(including the one that sent it).

Most of the code is a direct copy/paste from the enet tutorial. The
code is definitely not perfect but is suitable for a beginner to look
around in.

server.cpp

#SelectExpand
1/* server.cpp */ 2#include <stdio.h> 3#include <enet/enet.h> 4 5int main (int argc, char *argv[]) 6{ 7 ENetAddress address; 8 ENetHost *server; 9 ENetEvent event; 10 int serviceResult; 11 12 puts ("Starting server"); 13 14 if (enet_initialize () != 0) 15 { 16 puts ("Error initialising enet"); 17 exit (EXIT_FAILURE); 18 } 19 20 /* Bind the server to the default localhost. */ 21 /* A specific host address can be specified by */ 22 /* enet_address_set_host (& address, "x.x.x.x"); */ 23 address.host = ENET_HOST_ANY; 24 /* Bind the server to port 1234. */ 25 address.port = 1234; 26 27 server = enet_host_create (&address, 28 32, /* number of clients */ 29 2, /* number of channels */ 30 0, /* Any incoming bandwith */ 31 0); /* Any outgoing bandwith */ 32 33 if (server == NULL) 34 { 35 puts ("Could not create server host"); 36 exit (EXIT_FAILURE); 37 } 38 39 40 while (true) 41 { 42 serviceResult = 1; 43 44 /* Keep doing host_service until no events are left */ 45 while (serviceResult > 0) 46 { 47 /* Wait up to 1000 milliseconds for an event. */ 48 serviceResult = enet_host_service (server, &event, 1000); 49 50 if (serviceResult > 0) 51 { 52 53 switch (event.type) 54 { 55 case ENET_EVENT_TYPE_CONNECT: 56 printf ("A new client connected from %x:%u.\n", 57 event.peer -> address.host, 58 event.peer -> address.port); 59 60 /* Store any relevant client information here. */ 61 event.peer->data = (void*)"Client information"; 62 63 break; 64 65 case ENET_EVENT_TYPE_RECEIVE: 66 printf ("A packet of length %u containing '%s' was " 67 "received from %s on channel %u.\n", 68 event.packet -> dataLength, 69 event.packet -> data, 70 event.peer -> data, 71 event.channelID); 72 73 /* Tell all clients about this message */ 74 enet_host_broadcast (server, 0, event.packet); 75 76 break; 77 78 case ENET_EVENT_TYPE_DISCONNECT: 79 printf ("%s disconected.\n", event.peer -> data); 80 81 /* Reset the peer's client information. */ 82 83 event.peer -> data = NULL; 84 85 break; } 86 } 87 else if (serviceResult > 0) 88 { 89 puts ("Error with servicing the server"); 90 exit (EXIT_FAILURE); 91 } 92 } 93 94 } 95 96 enet_host_destroy (server); 97 enet_deinitialize (); 98 99 return 0; 100 101 }

client.cpp

#SelectExpand
1 2 /* client.cpp */ 3 #include <stdio.h> 4 #include <string.h> 5 #include <enet/enet.h> 6 7 8 int main (int argc, char* argv[]) { 9 ENetHost *client; 10 ENetAddress address; 11 ENetPeer *peer; 12 ENetEvent event; 13 char message[1024]; 14 int serviceResult; 15 16 puts ("Starting client"); 17 18 if (enet_initialize () != 0) { 19 fprintf (stderr, "Error initialising enet"); 20 exit (EXIT_FAILURE); 21 } 22 23 client = enet_host_create (NULL, /* create a client host */ 24 1, /* number of clients */ 25 2, /* number of channels */ 26 57600 / 8, /* incoming bandwith */ 27 14400 / 8); /* outgoing bandwith */ 28 29 if (client == NULL) { 30 fprintf (stderr, "Could not create client host"); 31 exit (EXIT_FAILURE); 32 } 33 34 35 enet_address_set_host (&address, "localhost"); 36 address.port = 1234; 37 38 peer = enet_host_connect (client, 39 &address, /* address to connect to */ 40 2, /* number of channels */ 41 0); /* user data supplied to 42 the receiving host */ 43 44 if (peer == NULL) { 45 fprintf (stderr, "No available peers for initiating an ENet " 46 "connection.\n"); 47 exit (EXIT_FAILURE); 48 } 49 50 51 /* Try to connect to server within 5 seconds */ 52 if (enet_host_service (client, &event, 5000) > 0 && 53 event.type == ENET_EVENT_TYPE_CONNECT) 54 { 55 puts ("Connection to server succeeded."); 56 } 57 else 58 { 59 /* Either the 5 seconds are up or a disconnect event was */ 60 /* received. Reset the peer in the event the 5 seconds */ 61 /* had run out without any significant event. */ 62 enet_peer_reset (peer); 63 64 fprintf (stderr, "Connection to server failed."); 65 exit (EXIT_FAILURE); 66 } 67 68 while (true) 69 { 70 serviceResult = 1; 71 72 /* Keep doing host_service until no events are left */ 73 while (serviceResult > 0) 74 { 75 serviceResult = enet_host_service (client, &event, 0); 76 77 if (serviceResult > 0) 78 { 79 switch (event.type) 80 { 81 case ENET_EVENT_TYPE_CONNECT: 82 printf ("A new client connected from %x:%u.\n", 83 event.peer -> address.host, 84 event.peer -> address.port); 85 86 event.peer->data = (void*)"New User"; 87 break; 88 89 case ENET_EVENT_TYPE_RECEIVE: 90 printf ("A packet of length %u containing '%s' was " 91 "received from %s on channel %u.\n", 92 event.packet -> dataLength, 93 event.packet -> data, 94 event.peer -> data, 95 event.channelID); 96 97 /* Clean up the packet now that we're done using it. */ 98 enet_packet_destroy (event.packet); 99 100 break; 101 102 case ENET_EVENT_TYPE_DISCONNECT: 103 printf ("%s disconected.\n", event.peer -> data); 104 105 break; 106 } 107 } 108 else if (serviceResult > 0) 109 { 110 puts ("Error with servicing the client"); 111 exit (EXIT_FAILURE); 112 } 113 114 } 115 116 printf ("Say> "); 117 gets (message); 118 119 if (strcmp (message, "exit") == 0 || 120 strcmp (message, "quit") == 0) { 121 break; 122 } 123 124 if(strlen(message) > 0) { 125 ENetPacket *packet = enet_packet_create (message, strlen 126 (message) + 1, ENET_PACKET_FLAG_RELIABLE); 127 enet_peer_send (peer, 0, packet); 128 } 129 130 } 131 132 enet_peer_disconnect (peer, 0); 133 134 /* Allow up to 3 seconds for the disconnect to succeed */ 135 /* and drop any packets received packets */ 136 while (enet_host_service (client, & event, 3000) > 0) 137 { 138 139 switch (event.type) 140 { 141 case ENET_EVENT_TYPE_RECEIVE: 142 enet_packet_destroy (event.packet); 143 break; 144 145 case ENET_EVENT_TYPE_DISCONNECT: 146 puts ("Disconnection succeeded."); 147 break; 148 } 149 } 150 151 152 enet_host_destroy (client); 153 enet_deinitialize (); 154 155 return 0; 156}

TeaRDoWN
Member #8,518
April 2007
avatar

Thanks! I'll check it out as soon as I have more time. Hopefully it works without any issues "straight out of the box". :)

bamccaig
Member #7,536
July 2006
avatar

I wrote a simple sockets program recently. The program can act as either a server or a client:

[bamccaig@krypton sockets]$ ./a.out --help
  ./a.out { -h | --help }
  ./a.out [ -H | --host=HOST ] [ -P | --port=PORT ]
          [ -s | --server ] [ -v | --verbose ]

    -h, --help
            Show this message.

    -H, --host=HOST
            Specify the host. This can be either an IP address (IPv4 or
            IPv6) or a domain name. For the client, this is the server
            to connect to. For the server, this is the interface to
            bind to.

    -P, --port=PORT
            This is the port to connect (client) or bind (server) to.

    -s, --server
            Specifies to act as a server (bind and listen). The
            default behavior is to act as a client (connect).

    -v, --verbose
            Be verbose.

[bamccaig@krypton sockets]$ 

Server

[bamccaig@krypton sockets]$ ./a.out --host=127.0.0.1 --port=1337 --server
Binding to '127.0.0.1' on port 1337...
client '127.0.0.1' connected...
client (127.0.0.1): This was a triumph.
client (127.0.0.1): I'm making a note here. HUGE SUCESS.
server: client '127.0.0.1' closed connection.
^C
[bamccaig@krypton sockets]$ 

Client

[bamccaig@krypton sockets]$ ./a.out --host=127.0.0.1 --port=1337
Connecting to host '127.0.0.1' on port '1337'...
> This was a triumph.
server (127.0.0.1): OK.
> I'm making a note here. HUGE SUCESS.
server (127.0.0.1): OK.
> quit
[bamccaig@krypton sockets]$ 

It doesn't do a whole lot yet, but it might help to get an idea for how sockets work. Currently the server always responds with "OK." and the "protocol" expects the client to talk, then the server to talk, back and forth (i.e., it's single-threaded, except for the server forking for client connections, with blocking sockets).

The code won't run in Windows though. Most of the socket programming should (with some preprocessor workarounds), but fork certainly will not. :P It might run in Cygwin though, but no promises.

The best way to learn socket programming is Beej's Guide to Network Programming. That's how I learned (both times). :) The basic order of things for a client is:

  1. Convert user-friendly address string and port to address data structure.

  2. Create socket.

  3. Connect to server using socket and address structure.

  4. Send and receive data.

The basic order of things for a server is:

  1. Convert user-friendly address and port to address data structure.

  2. Create socket.

  3. Bind to address using socket and address structure (technically a client can bind before they connect if they want a specific interface and port, but if they don't bind then connecting will bind for them).

  4. Listen for incoming connections.

  5. Accept incoming connection.

  6. Send and receive data.

If you use blocking sockets then you basically need threads to enable the server to handle multiple clients (and listen for more) and, if desired, for the client also, to send and receive simultaneously. If you use non-blocking sockets (which are a bit more work to setup) then you check instead whether there are new connections, whether there's data to send or receive, etc. No guarantee that it'll be useful to you, but here it is anyway. Again, it won't build in Windows (except for maybe Cygwin) so don't even try to build it. :P

AMCerasoli
Member #11,955
May 2010
avatar

--- ENet ---
Yes, I just compile it and it works fine.

I have just edited the code above, because I miss a "}" at the end. I took that example from those e-mail list with a bunch of <<<<< all over the place.

link to "libenet.a" if you did a static library or .dll depending. Also remember to link to "ws2_32.lib" and "winmm.lib" and include the "include" folder in your "search directory" and yes works straight out of the box.

Here it's... I think is better than Windows Messenger (just because I compile it) ;D

decepto
Member #7,102
April 2006
avatar

--------------------------------------------------
Boom!

ImLeftFooted
Member #3,935
October 2003
avatar

TeaRDoWN said:

Is there anyone who have made a small game or program and is willing to show it here or send it to me?

Ah man, you've brought me back.

http://www.allegro.cc/forums/thread/600909

It's almost been 2 years since I built that. Mm.... when is the next speedhack?

Oo, I should port this to the iPhone...

AMCerasoli
Member #11,955
May 2010
avatar

Wow decepto you have just posted a gold mine there...

One of those gold mines I read say this:

Quote:

Lets look at the properties of each:

TCP:

Connection based
Guaranteed reliable and ordered
Automatically breaks up your data into packets for you
Makes sure it doesn’t send data too fast for the internet connection to handle (flow control)
Easy to use, you just read and write data like its a file

UDP:

No concept of connection, you have to code this yourself
No guarantee of reliability or ordering of packets, they may arrive out of order, be duplicated, or not arrive at all!
You have to manually break your data up into packets and send them
You have to make sure you don’t send data too fast for your internet connection to handle
If a packet is lost, you need to devise some way to detect this, and resend that data if necessary
The decision seems pretty clear then, TCP does everything we want and its super easy to use, while UDP is a huge pain in the ass and we have to code everything ourselves from scratch. So obviously we just use TCP right?

Wrong.

Using TCP is the worst possible mistake you can make when developing a networked game! To understand why, you need to see what TCP is actually doing above IP to make everything look so simple!

And I just wanted mention that ENet (UDP) handle most of those things for you!.

@Dustin: Do you need a dedicated server to run your sever game? because I see still working...

ImLeftFooted
Member #3,935
October 2003
avatar

@Dustin: Do you need a dedicated server to run your sever game? because I see still working...

Yeah and the server is still up. Every so often it emails me an error. Kind of cool to know people are still playing it.

Update: http://momeme.com/traingame/

AMCerasoli
Member #11,955
May 2010
avatar

Hahahahahahaha so you're happy knowing people are getting errors from your game??

What company are you using? isn't that expensive or you have it for other purposes too.

I read somewhere that RakNet allows you to do some networking even if you don't have a dedicated server. I think I saw it in the video tutorial that is in their webpage. How can it be?. Something like reading and writing files?

PS: Did you know that your game has a lot of potential? but it's screaming for graphics. I'll download the update.

ImLeftFooted
Member #3,935
October 2003
avatar

You can do peer to peer connections -- but that's lame.

I use fluid hosting and pay $52/mo for a VPS with 4 ip addresses.

I run a bunch of domains out of it. Here's the list (although some are no longer active):
Screen_shot_2011-04-08_at_6.06.14_PM.png

Here's how many resources I get for that price:
Screen_shot_2011-04-08_at_6.07.04_PM.png

I can upgrade my resources a lot more before needing to move onto something more serious.

Hahahahahahaha so you're happy knowing people are getting errors from your game??

I made the game in 72 hours, I'm fine with it having glitches.

Update: There are cheaper places than Fluid Hosting but I stay here because their uptime is good. I went through 4 cheaper ones that were too unstable.

AMCerasoli
Member #11,955
May 2010
avatar

Oh I see... And if I want to use my own computer as a game server? I have a dynamic IP so isn't possible, at least I use something like no-ip.com, but they give me a url non an IP numer...

ImLeftFooted
Member #3,935
October 2003
avatar

Yeah no-ip works.

You'll have to worry about your router settings then. I would turn on the DMZ (De-Militarized Zone) on your router and set your computer's local ip as the DMZ destination.

AMCerasoli
Member #11,955
May 2010
avatar

I always wonder what can I do with a Dedicated Server (besides having a webpage or a game server)... For example can I install a 3D render program an let it doing rendering processes all the time?

Or they won't allow me to do that?

PS: I thought that that link was an update for the game :'(

ryonagana
Member #6,623
November 2005

Enet looks like quake 2 server/client broadcasting

c++

Derezo
Member #1,666
April 2001
avatar

AMCERASOLI: You can pretty well do anything legal with a dedicated server, but using it for 3D rendering would probably not pan out very well. With a VPS you get a set allotment of processing time. Places like Slicehost will allow you to use any "spare" CPU time that nobody else is using.

I run a simple web server with Slicehost. I like their setup a lot. It isn't super cheap, and the performance of my 256MB slice isn't super awesome, but it has been extremely reliable and consistent. In the last ~18 months there's been one hardware failure at 3am which was fixed by 4am and I received about 4 status updates via email informing me of the progress of the whole situation. I was impressed.

"He who controls the stuffing controls the Universe"

Elias
Member #358
May 2000

Our dedicated server at corenetworks has a better CPU than my desktop, so it would be ideal for e.g. rendering a blender movie (if i had the server all for myself, that is). The biggest benefit would be that the fan noise of my desktop would be kept down :)

--
"Either help out or stop whining" - Evert

AMCerasoli
Member #11,955
May 2010
avatar

Oh nice, yes because I was trying to justify having a dedicated server, currently I have no need but if could let it rendering some graphics, having my webpage, and a game server (when my game is ready) I might rent one, but what I need for my game is just a online score table... and my webpage is currently hosted for only 25 E/Year so... I don't need it so far.

Now talking about other thing...

I'm studding the way to have an online score table (the best 12 players) using HTTP, it's that possible?. So far the problem that I have found is that I could upload the info but then the program (client) should download the 12 files which contain the name of the players and the scores and then compare if the score of the client is better that those downloaded form the server and if it is, save it with the specified number position, let's say "3.dat" then upload that file to the server overwriting the one that is there... But if there are 100 people playing the game and doing that process I think would be a little messy and discoordinated, but I could do it I don't know...

I was reading this http://www.example-code.com/vcpp/http.asp but I have no idea I haven't finished my game and this would be the final step if it's possible...

bamccaig
Member #7,536
July 2006
avatar

You should use a database that supports atomic operations to store the score info. Then your application would lock the hiscores table, compare the new score to the lowest in the table, and if necessary replace it (i.e., UPDATE or DELETE + INSERT; it's semantics mostly). Then generate the Web page dynamically using an application server technology (PHP, ASP.NET, CGI, etc.). You could even use HTTP POST and an application server technology to handle the submission of a score. It would just be a matter of connecting to your Web server and writing some bare minimum HTTP text into your socket. Or you could write your own server, or use many other alternative server technologies... Of course, whatever solution you use, it runs the risk of leaving the server vulnerable to hackers if you don't do a good job. :P

You don't have to use a database, but it's the more reliable way aside from writing a complex platform-dependent atomic solution yourself. :)

AMCerasoli
Member #11,955
May 2010
avatar

I din't explain well myself, but you gave me a good idea (show the score on a webpage too), Or maybe I'm not understanding you. I want to show the table inside the game. For that reason the game should download the files then compare and then upload just one file if it is necessary (a better score) and overwritten the old one. Now it comes to mind another existential problem? what happens if someone gets exactly the same score than another one that is already on the list? should overwrite it?, or should stay there since was the first one?. :P

Samuel Henderson
Member #3,757
August 2003
avatar

I din't explain well myself, but you gave me a good idea (show the score on a webpage too), Or maybe I'm not understanding you. I want to show the table inside the game. For that reason the game should download the files then compare and then upload just one file if it is necessary (a better score) and overwritten the old one. Now it comes to mind another existential problem? what happens if someone gets exactly the same score than another one that is already on the list? should overwrite it?, or should stay there since was the first one?.

I would do as bamccaig suggested and run an SQL database (SQLite, MySQL, Postgres, etc) on your dedicated server. In your game, you would use an SQL library to connect to your SQL database and 'SELECT' the highscores from the highscores table. Your game wouldn't have to download/upload any files.

As far as overwriting highscores that are the same... that is purely up to you. Personally, if I was playing a game and saw that my score matched the lowest score in the top 10 I would not be expecting to enter my name since I've always viewed the scores as 'Must-be-better-than' to place and not 'must-be-better-than-or-equal'

=================================================
Paul whoknows: Why is this thread still open?
Onewing: Because it is a pthread: a thread for me to pee on.

AMCerasoli
Member #11,955
May 2010
avatar

That sounds cool. But can I do that without a dedicated server? because that was my point. Or is going to be alway necessary a dedicated server?. Can't I use FTP or something?.

bamccaig
Member #7,536
July 2006
avatar

I want to show the table inside the game.

Oh, OK. I did misunderstand you. I thought you wanted to show the scores on a Web site. Nevertheless, I'd still encourage an RDBMS solution.

Now it comes to mind another existential problem? what happens if someone gets exactly the same score than another one that is already on the list? should overwrite it?, or should stay there since was the first one?. :P

I'd agree with Samuel Henderson. You should have to beat a high score to make the list, not just match it.

That sounds cool. But can I do that without a dedicated server? because that was my point. Or is going to be alway necessary a dedicated server?. Can't I use FTP or something?.

Assuming you want high scores to be shared by all players you need to centralize the high scores table. For this you basically need a centralized server. I'm not sure exactly what you mean by a "dedicated" server, but I don't think it matters; it's not necessary. You could use a VPS instead, or your own desktop if it is accessible from the Internet (which can be dangerous, but I digress). As for FTP, I don't think FTP is a reliable way to update the high scores table. I don't use FTP myself, so I could be wrong, but I doubt there's any way for FTP to atomically lock a file, download it, and sometime later update it... I doubt it anyway. In either case, it's a rather sloppy way to do it, IMHO. :) I'm beginning to think that you're currently using some Web space provided for cheap with only FTP access and no direct access to the server. I don't think that you'll be able to achieve a reliable solution with a setup like that. FTP is just not a very good way to do this. I'm currently paying $11/month for a VPS with more than enough power for this. If that's too much then you're probably SOL unless you can convince somebody else with a server to spare you a database. :)

Arthur Kalliokoski
Second in Command
February 2005
avatar

bamccaig said:

You should have to beat a high score to make the list, not just match it.

IMO that means you don't have a fine enough granularity for the score. It's still possible to match a score, but highly unlikely.

[EDIT]

I suppose a devastatingly simple game like Pong would be exempt.

They all watch too much MSNBC... they get ideas.

 1   2 


Go to: