Legacy GM Using TCP and UDP at the same time

Anixias

Member
Now, I'm already aware of what I should probably do. Have a TCP socket that the clients use to connect to the server and send information that needs to be reliably sent, and also have a UDP socket that they send pretty much everything else through.

Well, my game is 100% UDP at the moment, and I even have connections, disconnections, and timeouts built in. But, now that I'm allowing custom graphics and stuff to be sent to the server, I need it to be more reliably sent. I need to use TCP. So, is it possible to use TCP without setting up connections? Or should I delete my current connection/disconnection/timeout code and replace it all with TCP?

Or can this be done in a different way? Is my idea completely wrong? Thanks for reading.

EDIT:
Just had a thought.
Would the server have to call network_create_server twice? Once for UDP and once for TCP?
 
Last edited:
M

Mishtiff

Guest
I am actually glad you posted this, because i planned to ask the same question. will be following for info.
 

Anixias

Member
I exported my game to a GMZ and I am now going through what I think is the right process. What I've done is create two sockets for the server (one with network_create_server of type TCP and one with network_create_socket_ext of type UDP) and two sockets for the client (one with network_create_socket of type TCP and one with network_create_socket_ext of type UDP) and I am currently going through the process of changing a lot of things to work with four sockets rather than two. So far, I have proper connections, but since my original UDP timeout stuff is still in the code, after 5 seconds, I teleport to 0,0 and I am no longer in control of my ship. I am gradually changing everything to work. I might end up deleting it all and just completely redoing it all. I exported in case I ruin my game, so I can just revert to when it worked.
 

Freddy Jones

Your Main Detective
I would highly advise against mixing UDP and TCP together. Stick with one or the other, otherwise you will have some bigger problems on your hands.

For example, using both together increases the rates of packet loss. Your UDP packets which are already unreliable to connect to begin with are going to be far more unreliable, and your usually guaranteed TCP packets will have to be resent and clog up the queue waiting for lost tcp packets more frequently.

Overall you'll have a much larger drop in efficiency than increase in efficiency.

What I'm saying is off the top of my head, but near the dot somewhere. It might be flipped, but I'd look into this topic: tcp starvation/udp dominance.


If I were you I'd take some time making a system that can reliably take streams of data over UDP -- I'm sure there's solutions out there so you don't have to reinvent the wheel. But TCP by itself is not too slow for most games nowdays.
 
D

dj_midknight

Guest
Make the client confirm that it received the image possibly?

You could create a hash signature as GMS does have an inbuilt method for SHA1 smash the generated image through SHA1 store the hash. Then send everything to the other client/server have it do a hash on receive then send the hash back to ensure that the data all arrived.

One step further you can tack the hash onto the end of the packet so the receiving client can compare hashes and then if needed have it send a resend request.
 
Last edited by a moderator:

Anixias

Member
I honestly thought about doing that but there are a couple problems:
  1. Since I'm using only UDP, and the images can be large (around a MB), I can't just send the image. It literally will not send, unless the buffer is containing a fairly small amount of data. A few KB is all before it ignores my request to send the image.
  2. There is the chance that packets are just randomly dropped, so I would have to keep resending a resend request until either satisfied with the resend or disconnected from timeout.
Since I shouldn't mix the two, how should I send images or large files? I thought about reading it as a string. The whole file into one string, and as long as the buffer is not too large, add the first character of the string to the buffer and delete that character. But, I can't just keep writing buffer_strings to a buffer, that would inflate so much.

I honestly have no clue how I should send large files with UDP. Any help?
 
D

dj_midknight

Guest
First you really need to look into compressing that data. Network bandwidth is not cheap on a large scale. Find some way to convert the graphic into a smaller format before sending it. I know GMS supports PNG so I would look into that
Next UDP theoretical packet size max is about 63.5KB.

Ok now moving on you shove your image into a buffer, ill ask my partner which GMS can use for this as I am not as fluent with the network stuff as he is.
So you slice off each say 1KB chunk(network hardware prefers this, 500B for max comparability) index it, hash it, sign it, and send it. Rinse and repeat until all data is sent.
Now if the receiving end does not get a certain index it requests a resend of that chunk, or if something fails to hash check ask for a resend.

In this manner you can basically just fire off packets until the buffer is empty as fast as your own network can handle it and then let the receiving end tell you what data to resend.

This will require that each chunk be stored in an array until all data is received and can be recombined.
 

Anixias

Member
That was my original idea but using the buffer_get/set_surface functions hasn't worked once since I've started this game, I've tried using them for non-networking stuff too. I despise those functions xD Anyway, I will try that, but first I need to find out how to "slice off each 8KB". Can you get the number of bytes from a string? If not, how would I split this data up?

EDIT:
Ohh found the function string_byte_length in the manual.
 
D

dj_midknight

Guest
Ok so I just consulted with my partner he recommends stuffing the data into a byte buffer as this can be sized to whatever you need. You will want to use buffer_copy which requires you tell it where to start and where to end the copy to get your slices. It also occurs to use you will probably want to send a leader packet first which informs the receiving end how many slices it is going to receive. That will allow the client to prepare a sufficiently large array upfront.

So in a perfect world this is probably the sequence you want to follow.

Raw data pushed into compression algorithm.
Hash compressed data.
Compressed data pushed into byte buffer.
Leader packet sent with byte buffer / packet size and complete signature.
Fire off sequence of packets each indexed and hashed until data fully processed.
Resend any lost data.
Compile received data into a single buffer.
Hash complete data set.
Process in game.
 

Anixias

Member
Alright, I will see what I can do. Thanks for the help!
EDIT:
What exactly is a "byte buffer"? And, why would I pass the compressed data to this "byte buffer"?
 
Last edited:
D

dj_midknight

Guest
Byte buffer holds raw bytes of data and is able to be manipulated by buffer_copy so that you can slice it up into chunks.
 
F

Fishman1175

Guest
Hate to cut in part way, but there isn't a good reason you can't use TCP and UDP at the same time. I use both for the exact reason you say, you want most things to be udp but some things need guaranteed transmission. Freddy Jones's post is mostly incorrect when you consider routers are configured to drop Udp packets first rather than TCP packets because of the overhead TCP has. Even still, this is only in extreme cases. If you don't want your Udp dropped, don't use Udp for that information. You won't have bigger problems if you mix them. Professional games do it successfully all the time. You just have to use the right protocol for the right information.

Some good discussion if you're interested: http://stackoverflow.com/questions/8157224/tcp-vs-udp-issues-that-arise-from-using-both
 

Anixias

Member
So, it should be fine if I just use TCP for something like file transfers and connections?

Too bad I already undid the swap to TCP/UDP ):
 
Top