Tcp Server/Client Sockets

Monkey Forums/Monkey Programming/Tcp Server/Client Sockets

Hezkore(Posted 2014) [#1]
I'm trying to figure out how to work with Tcp sockets.
I've tried out the examples that come with Monkey X, but they don't help me that much.
The problem is when a lot of data stacks up... when it's sent ontop of each other, it sorta creates a mess of data I don't know how to handle.
Especially when the server runs faster than the client does!

So I've got this example of my problem, and I thought maybe we all could work together to shape this into a sort of basic Tcp Server/Client Framework?
I'm no good at network stuff, so this whole thing might be useless, but I really think Monkey X need some sort of solid network framework and I think that this could be turned into something good.


In this example the client will send 3 messages to the server, which works fine.
Then the server will respond with another 3 messages back to the client, and because the client runs slower than the server, the data will be messed up and things will end badly!
You'll also see "RACE!" being printed and I have no idea what that is about...
UPDATE: Seems like the newest Monkey X versions fixed that message!

In client.monkey, if you remove
If UpdateRate > 4500000 Then
The client will run as fast as the server, which will "fix" the issue.
This of course isn't a solution.

This example code was made for the C++ Tool Target.

CODE REMOVED

Now found on BitBucket: https://bitbucket.org/Hezkore/monkey-x-tcp-module


Hezkore(Posted 2014) [#2]
Alright, I've made some progress and figured out a few things.
This seems to work pretty well right now, but any input is welcome!
Keep in mind that a lot of things are in test/debug mode.

I'll finish this up, clean up the code and eventually put this on BitBucket.

CODE REMOVED

Now found on BitBucket: https://bitbucket.org/Hezkore/monkey-x-tcp-module


golomp(Posted 2014) [#3]
Wow. My god. Congratulations for your work.

Thank you

Golomp


Hezkore(Posted 2014) [#4]
Thank you!
It's not really ready to use yet and needs a lot of shaping up, but it's getting there!

I'm going to remove as much DataBuffer slicing as I can.
Add client join/part as packets for the server, as well as a error packet the server can send to the client.
And also a ping packet that will measure client response time and test if they're still an active client.


Hezkore(Posted 2014) [#5]
This has been turned into a module over at BitBucket: https://bitbucket.org/Hezkore/monkey-x-tcp-module
It comes with a Server and Client example and should work on all targets that supports brl.socket, and it does everything asynchronously.

I've gotten rid of a lot of DataBuffer slicing.
The server now gets both a JOIN and a PART packet when clients connect or disconnect.
You can disconnect clients with a custom error message.
Ping packets are not in yet.
Clients has a UserData Map you can store information in.
And I've noticed that Floats are sent as Ints for some reason, not sure why that is...

Any input is still welcome, and feel free to push commits to the repo!


Xaron(Posted 2015) [#6]
Nice stuff, I like it! Will play around with it. Thanks for sharing! :)


ImmutableOctet(SKNG)(Posted 2015) [#7]
@Xaron: If you're interested, at least as an example, I wrote this before. To actually use it, you'd need my other modules, though. That module's still experimental, but it works for both TCP and reliable UDP. And from what I remember, I had an internal-message system going, which supports pinging. Nothing "production ready", but if you find it useful, by all means take what you want from it.

The main modules it needs are:
* 'util'
* 'eternity'
* 'byteorder'
* 'publicdatastream'

Because there's several imports, and I haven't marked it as stable, if you want to use the module normally, you'll want to recursively clone this repository. Honestly, it's probably better to just look the code over yourself.


Xaron(Posted 2015) [#8]
Thanks, will check it out as well! :)


Duke87(Posted 2015) [#9]
very nice work!

I'm playing around a little bit with your code.
How do I send a broadcast to all connected Clients ?

i have managed to code a little Chat. Everything's fine. When i start 2 Clients, it shows me that there are 2 Clients connected.

now, I've changed:
Server.StartPacket(PACKET_MESSAGE)
Server.Packet.AddString(Packet.ReadString())
Server.SendPacket()    '<<< shouldn't this now be kind of broadcasting to all?


but my Server quits with mav.



edit:
Now I've recoded the servercode.
And everything's fine. I can connect 2 different Clients. When i press Space, it sends a message, but only the sending client receives it's own message.




Hezkore(Posted 2015) [#10]
It's been a long time since I worked on this, and I'm not by the compter today....
But I don't think the server just bounces the message to eveyone on its own.
When you send a packet, you send it to the server and then you need to tell the server what it should do with that information.
Like, all "chat" packets could be sent to all clients if you wish, but you need to code that.
And all "login" packets (which you certainly don't want to broadcast to everyone) could be checked against your user database.

Basically, the user doesn't have control over what's broadcasted or not, you code your server to handle all that.
All messages are sent to the server where you have full control over what happens next.

In the server you can see the line which goes something like SendPacket(From.Packet)
Which means it just sends the packet back to whomever the packet came from.
I believe that if you remove From.Packet, it might send to everyone.

Or I can throw together a "send to all" example at some point. :)


rIKmAN(Posted 2015) [#11]
I missed this first time around, definitely going to have a look at this as it sounds great.

Thanks for sharing!


Duke87(Posted 2015) [#12]
Hi,

Ok, now I got it running with a very cheap solution. But it works.

within the sending routine of Server-app:
For Local i:Int = 0 Until Server.getClientCount()	
    Server.StartPacket(PACKET_BROADCASTMASSAGE)
    Server.Packet.AddString(str)
    Server.SendPacket(i)
Next 


I also added to TcpServer Class
Method getClientCount:Int()
	Return ClientArray.Length()
End Method

I expacted to get only the number of connected Clients, but it returns the max number of possible Clients, so i also had to change the SendPacket Method of TcpServer

If Self.ClientArray[client] <> null
	Packet._socket = Self.ClientArray[client].TcpSocket
	Packet._onComplete = Self.ClientArray[client]
	Self.PacketSendQueue.AddLast(Packet)
Endif


I may add a getConnectedClientID:int[]() returning all Client IDs which are connected to the Server,
So you can do something like:

Local cID:Int[] = Server.getConnectedClientID()
	For Local i:Int = 0 Until cID.Length()
					
	    Server.StartPacket(PACKET_SECUREMASSEGE)
	    Server.Packet.AddString(str)
						'Send packet to specific client
						'Leave empty to send to all clients
	    Server.SendPacket(cID[i])
	Next