Archived

This topic is now archived and is closed to further replies.

Dunge

sockets/c++/real time game/accept()

Recommended Posts

Ok.. I want to make one of my OpenGL game playable over internet (or LAN). I looked a bit over win32 sockets and understand I need to do (exemple for the server): WSAStartup socket bind listen accept send/recv while the game is playing close WSACleanup but the problem I get is that for the accept and recv function, every code I read use infinite loop until someone actually connect or send data... this is ok for dos but I don''t want my opengl game to stop until someone connect, I want them to connect anytime in the game.. someone told me to look at threads but it seem a bit complicated for nothing, I guess there is another way??! thx for the help!

Share this post


Link to post
Share on other sites
First: if your game is real-time, TCP sockets are not going to treat you well. You need UDP for real-time games.

Second: if you want to accept() without blocking, you can select() on that socket, and it''ll come back as readable if there''s anyone waiting on it. Then call accept() to return the connected socket.

But use UDP. Or a network abstraction layer. (HawkNL, perhaps?)

Share this post


Link to post
Share on other sites
Ok,.. here the update.
I used this tutorial : http://www.gamedev.net/reference/articles/article1297.asp
it's pretty good, exactly what I want, receive the connection attemp/data/close/etc in windows messages so it's great.

The problem is that he use TCP (stream)... and I tried with that the bind and listen (server) and connect (client) return 0 (no error) but the server didn't get any FD_ACCEPT message.

switching to UDP like you said is faster, I found out that we don't nee listen since it always listen. Well automaticly when the server start it receive an FD_WRITE message (wtf?).. the client when using connect it return 0 (no error) and when using send() it return the number of byte so it should be ok but again, the server don't receive any FD_READ messages

[edited by - Dunge on March 29, 2004 12:18:53 AM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
UDP is is a very simple low level protocol; it simply sends a fixed size packet via a known route to the other end. There''s no reliability inbuilt; the protocol does not send a packet in reply saying "I got that one". It is also not sequenced, which means packets could arrive out of order.

TCP is a sequenced, stream based (bytes, not packet), reliable protocol all of which requires the protocol to only deliver information to the application when it knows it has the right piece of information. However, TCP works fairly well in good conditions; if there''s no packet loss then you get the packets in a timely fashion. However loose just one packet (which is not as rare as you might think) and TCP has to organise the other end to retransmit; this will loose you at least one round trip. In the meantime, nothing else gets through; since the data has to arrive in sequence. This means TCP would stall your data on any packet loss.

This would be a problem for first person shooters, or other fast paced games where you want bulk transfer of time critial data (ie. player positions that move rapidly). So, it really depends on what the data is for; for example TCP is very good for http, ftp, and other bulk transfer of data where it''s important to get it all, in the right order, but time is not as important. UDP is good if you want it now, but any delays means the data is worthless - consider the position of a fast moving plane.

Most games still use UDP, because you can implement your own relability, retransmission and ordering qualities on top of the protocol for maximum control. Writing a fully fledged version of TCP is not what you want; a good place to start is simply adding a sequence number (each packet is numbered incrementally) so you can spot missing or out of order packets and handle them appropriately.

In summary; TCP great, UDP great. But for most game data (except Chess) you probably want UDP. You might want to use TCP for bulk transfer of content or for accounting purposes however.

Hope that helps...

Viper

Share this post


Link to post
Share on other sites
Thanks, but could you explain how it works like in starcraft?
every udp packade is sent to the server, who puts them together in a new one and sends it to all the players?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I believe starcratf, like most other strategy games, use Star-type architecture. Basically, when a client needs to send something, it will send it to ALL players (or appropriate team players, if there are teams...) That way, if the host Disconnects, the others can still continue playing, wich is not the case with games like FPSes or MMORPGs, where the client sends everything to a single server, and the server sends to every client, and there are no packages sent between clients...

Share this post


Link to post
Share on other sites
That''s not a "star" topology; if everyone sends to everyone, then it''s a "fully connected" topology.

A "star" topology is when everyone sends to one node (the "server" "hosting" the game) and then that node echoes back to all the nodes. That will, of course, fail, if the centerpoint of the star (the machine hosting the game) fails, the game fails.

If you want to be more resilient, then all players need to have the address of at least one other machine to use as the back-up host, and use that when the main host fails. (You can of course go deeper into this kind of design)

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Hi, I''ve got a question. I''m using UDP, and in my serverthread I wait for packets that arrive from a client. I have to know the client socket from which the packet was sent. With UDP, do I have to listen on a port? I thought I just use accept() and that will give me the address of the socket. Is this right?

Share this post


Link to post
Share on other sites
To use UDP:


s = socket( ... IPPROTO_UDP ... )
inaddr.sin_addr = INETADDR_ANY;
inaddr.sin_port = htons( MY_PORT );
bind( s, ... &inaddr ... )

while( 1 ) {
recvfrom( s, ..., &oneOfMany );
deal_with_message_from( &oneOfMany, ... );
}


There are no connections in UDP, thus there is no "accept()," only "bind()" and recvfrom/sendto.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Thnx a lot, I''m gonna try it right now.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Original post by Anonymous Poster
UDP is is a very simple low level protocol; it simply sends a fixed size packet via a known route to the other end.

AFAIK every UDP datagram is routed independently of other datagrams.

And ''lose'' has only one o in it.

Share this post


Link to post
Share on other sites
OK, but imagine my server is constantly running.. and i want to take connections from clients as they come.. surely i can''t use recvfrom until i know where it''s going to come from..... and i cant know that until i recvfrom someone.

stu

Share this post


Link to post
Share on other sites
This is why I don''t like sockets. When it comes to threading and accepting more clients at once, you HAVE to build a system around it.

Short answer, create a system that manages SOCKETs and for every SOCKET you have to create a thread that recv()''s fromt that SOCKET.

--
You''re Welcome,
Rick Wong

- sitting in his chair doing the most time-consuming thing..

Share this post


Link to post
Share on other sites
The address argument to recvfrom() tells you who sent the data, it does not select who to receive data from. For more information, I suggest googling, MSDN, or reading the man page.

Share this post


Link to post
Share on other sites