Handling Socket Streams

BlitzMax Forums/BlitzMax Programming/Handling Socket Streams

foosh(Posted 2008) [#1]
So I'm writing a multiplayer client using a TCP Server written in Python, and the client written in BlitzMAX. The problem is, sometimes the server will send junk packets or blank packets (because the client is using ReadLine, so it has to receive an endline character), and the client gets backlogged. Is there any way in BlitzMAX to just read the latest packet from the stream, or to not even read blank packets? The problem is that in order to check if a packet is blank, I have to read it and process it....

Any suggestions?

Thanks!
foosh


Dreamora(Posted 2008) [#2]
If you want to have a usefull TCP performance in Blitz I would suggest sending packets of constant or at least defined size, not "free size" packets and just read into the blue.

Because then you can in your TCPStream Object just read X bytes and operate on that data.
reading byte by byte is hellish slow just to find the end of a line.


foosh(Posted 2008) [#3]
Say the data sent is too short or too long. If it's too short, then it'll read into another set of data, if it's too long, it won't read far enough.

I wasn't aware that ReadLine was that much slower, but at this point, I'm unsure how to do it without reading a set amount of bytes...

Thanks in advance for any additional help
foosh


Dreamora(Posted 2008) [#4]
there is no too short and too long.

you read a byte -> message ID
you read an int or short -> message size
you read bytes of the number of message size -> packet end, parse the packet content.

that means that you logically have to store the size within the message but thats clear that this is needed, there is no way around that if you send strings for example.
To get usefull information on how such stuff can be done, there are some tutorials mainly targeted at UDP but the concept is the same for TCP. just writting stuff blindly on the stream and read out each byte till "endline" was sent is trash. thats something you can only do for a html parser for example (connection to meta server) but not for anything that is meant to work near realtime!

EDIT: On messages that always have the same size you don't need to store the size. in those cases you can just react to the message id. position update and the like for example.


foosh(Posted 2008) [#5]
It seems like using that method is more trouble than it's worth. At most, you're saving a handful of CPU cycles, and there is a much larger room for error.

For now I think I'll stick with ReadLine, and just find a quick workaround. (Shouldn't be too hard)

Thanks!
foosh


daaan(Posted 2008) [#6]
foosh = foolish


Dreamora(Posted 2008) [#7]
it is no trouble at all.
it has nothing to do with saving cpu cycles if you use readline.
you are degrading the TCP to a hundred message per second protocol by using it with your "kill it for sure approach"

You can decide between doing it correctly or make sure that you will degrade it to turnbased networking.

Don't see why you actively want to not understand the network basics but still program network code. perhaps doing it non networked first so you have time to research on network programming would be the wiser step in this case instead of writting the code twice.

Simply said what you must do is send message object and the size etc is nothing else than what you write and read in regular object serialization onto a stream, in this case a TCP stream.


foosh(Posted 2008) [#8]
First of all djw, I don't appreciate your comments. They're not constructive or necessary at all. You should first read up on networking before you enter a discussion you know nothing about.

Dreamora-- don't worry I'm a computer scientist and I fully understand networking. I don't mean to be rude, but please don't demean me when I have been completely polite with you. I don't understand the reasoning behind your explanation.

I don't know what the "right" way is, but your way sends more data from the server by adding on additional information before the message. So at the network level, it slows down the network by sending additional bytes of data.

I'm not quite clear on what you mean by "degrading the TCP to a hundred messages per second." I hope you don't mean reading from the stream, because that doesn't slow down the network at all-- a stream is just a queue of messages received from the server that you're reading from. Therefore, the only difference between ReadLine and ReadByte is that of CPU cycles (just reading from memory), which is an incredibly small speed increase, if any.

Please explain "degrading the TCP to a hundred messages per second," so I can understand your reasoning.

One again, there is no need to demean me when I'm just trying to be polite.

Thank you,
foosh

EDIT: It's very important I understand your reasoning so I know how exactly ReadLine is, in your opinion, killing the network.

EDIT 2: Since my question wasn't really answered on these forums, I discovered the command SocketReadAvail() which was exactly what I needed.


Ked(Posted 2008) [#9]
I discovered the command SocketReadAvail()

So you're saying that in the beginning you were just reading without seeing if there was anything there?


foosh(Posted 2008) [#10]
No, I was looking for non-blocking calls, but I don't think BlitzMax supports them, and I recently stumbled upon ReadAvail, which didn't work for some reason, and then SocketReadAvail() did. It's the closest you can get to preventing network blocking without having multi-threading.

foosh


Retimer(Posted 2008) [#11]
Would take longer and i'm sure you aren't looking for a suggestion like this, but with networking, if you are limited to TCP I suggest going straight c++ with the client where you aren't so limited.

Otherwise, you would have a lot more to play with in blitz, if you went r-UDP with the server, and continue the client in blitz.

If that is a possibility, I would check out Enet (as dreamora always suggests). It's extremely stable from what i've seen in it and is easily customizable to your needs.


@djw
You are the first person on this forum that I have seen that has made an insulting comment towards another poster like that. We aren't with you on comments like that; this isn't highschool, so don't waste your breath.


Dreamora(Posted 2008) [#12]
Why readline is a problem: it will block the program until it received the full line. so if you send a line with a larger number of bytes your whole application will have to wait until linebreak is received, no mather how long this takes! (-> degrade to turn based)
Thats the problem with undefined sizes, you can not easily check for their full presence as well.

With fixed packet sizes you wouldn't have that problem. you could check how many bytes are available and if number of bytes > packetsize you just read the number of bytes (-> the packet) and thats it. if they are not ready you just skip the readout step in this loop (-> no block)

There is an example on how using this in the code archives. not sure thought if it is for BM or Blitz3D. but it still shows the basic idea of why and how.


Ked(Posted 2008) [#13]
You are the first person on this forum that I have seen that has made an insulting comment towards another poster like that.

Read some more threads.


foosh(Posted 2008) [#14]
@dreamora: okay that makes more sense-- that will fix lots of scaling issues when there are more packets flying around, and the client doesn't receive the full line of data right away. so far (with small scale testing up to 50 users), it hasn't been a problem, but i'll implement it to prevent problems in the future.

@retimer: thanks for the suggestions, i'll look into UDP. i have experience with c++, but is has a much higher overhead for starting game programming. i could take advantage of blitzmax's ability to interface with c to have more control over networking, however. (i don't know if that's what you meant)

foosh