Code archives/Networking/UDP Networking Class

This code has been declared by its author to be Public Domain code.

Download source code

UDP Networking Class by JoshK2008
This is a base networking lib on top of which more advanced features can be added.
SuperStrict

Import brl.socket
Import brl.map

Type TNetNode
	
	Const LOCALIP:Int=2130706433
	
	Global map:TMap=New TMap
	
	Field socket:TSocket
	Field ip:Int
	Field port:Int
	
	Method SendNetMessage:Int(recipient:TNetNode,data:Byte Ptr=Null,size:Int=0)
		If ip<>LOCALIP Return False
		Return sendto_(socket._socket,data,size,0,recipient.ip,recipient.port)
	EndMethod
 	
	Method GetNetMessage:TNetMessage()
		If ip<>LOCALIP Return Null
		Local message:TNetMessage,size:Int,ip:Int,port:Int,buf:Byte[]
		size=socket.ReadAvail()
		If size
			message=New TNetMessage
			message.data=New Byte[size]
			recvfrom_(socket._socket,message.data,size,0,ip,port)
			message.sender=Create(ip,port)
			message.size=message.data.length
			Return message
		EndIf
	EndMethod
 	
	Method WaitNetMessage:TNetMessage(timeout:Int=0)
		Local time:Int
		Local message:TNetMessage
		time=MilliSecs()
		Repeat
			message=GetNetMessage()
			If message Return message
			If timeout
				If MilliSecs()-time>timeout Return Null
			EndIf
			Delay 1
		Forever
	EndMethod
	
	Function Create:TNetNode(ip:Int,port:Int=41000)
		Local netnode:TNetNode
		netnode=Find(ip,port)
		If netnode Return netnode
		netnode=New TNetNode
		netnode.ip=ip
		netnode.port=port
		If ip=LOCALIP
			netnode.socket=CreateUDPSocket()
			If Not BindSocket(netnode.socket,port) Return Null
		EndIf
		map.insert netnode,netnode
		Return netnode
	EndFunction
	
	Function Find:TNetNode(ip:Int,port:Int=41000)
		Local netnode:TNetNode
		netnode=New TNetNode
		netnode.ip=ip
		netnode.port=port
		netnode=TNetNode(map.valueforkey(netnode))
		Return netnode
	EndFunction
	
	Method Compare:Int(o:Object)
		Local netnode:TNetNode
		netnode=TNetNode(o)
		If netnode.ip>ip Return 1
		If netnode.ip<ip Return -1
		If netnode.port>port Return 1
		If netnode.port<port Return -1
		Return 0
	EndMethod
	
EndType

Type TNetMessage
	
	Field sender:TNetNode
	Field data:Byte[]
	Field size:Int
	
	Method ToString:String()
		Return String.fromCString(data)
	EndMethod
	
EndType

Function CreateNetNode:TNetNode(ip:Int=TNetNode.LOCALIP,port:Int=41000)
	Return TNetNode.Create(ip,port)
EndFunction

Function SendNetMessage:Int(sender:TNetNode,recipient:TNetNode,data:Byte Ptr,size:Int)
	Return sender.SendNetMessage(recipient,data,size)
EndFunction

Function GetNetMessage:TNetMessage(recipient:TNetNode)
	Return recipient.GetNetMessage()
EndFunction

Function WaitNetMessage:TNetMessage(recipient:TNetNode,timeout:Int=0)
	Return recipient.WaitNetMessage(timeout)
EndFunction

Comments

JoshK2008
Here is an example of usage:
SuperStrict

Framework brl.system

Import "network.bmx"

AppTitle=""

Local client:TNetNode[2]

client[0]=CreateNetNode(HostIp("127.0.0.1"),80)
client[1]=CreateNetNode(HostIp("127.0.0.1"),81)

SendNetMessage(client[0],client[1],"Hello!".toCstring(),7)

Local message:TNetMessage=WaitNetMessage(client[1],1000)
If message Notify message.ToString()



BlitzSupport2008
Looks handy, thanks.


Chroma2008
Very clever and streamlined. So how many players could this handle without threading?


BlitzSupport2013
Anyone tried using this? The example program creates both client and server, so can 'see' both TNetNodes.

However, if you put the server in one program and the client in another, each program has no knowledge of the other TNetNode information.

I've just done a little hack that manually creates a TNetNode to represent the opposite party, setting only the other party's IP and port, and seems to work, but does this seem like a sensible approach?

SERVER:



CLIENT:



I've also taken out the references to LOCALIP, which I assume were just for testing purposes on a single PC, as they'd prevent sending over a network in a real situation:

UDPNET.BMX:




BlitzSupport2013
I set this up in two separate MaxIDE instances, side-by-side, so I can see the server Output tab while 'playing' in the client (left/right keys), but I notice some garbage coming into the output now and then, eg:

LEFT
LEFTT
LEFTTo
LEFTT


I know packets can be lost, etc (though presumably this would be almost non-existent on localhost), but any ideas as to where the extra characters might be coming from? I don't even send a lower-case 'o' from the client!


Henri2013
Hello,

size variable seems to remain constant, so if you change this method from the UDPNET.bmx:
Type TNetMessage
	
	Field sender:TNetNode
	Field data:Byte[]
	Field size:Int
	
	Method ToString:String()
		Return String.fromCString(data)
	EndMethod
	
EndType

...to this:
Type TNetMessage
	
	Field sender:TNetNode
	Field data:Byte[]
	Field size:Int
	
	Method ToString:String()
		Local s:String
		For Local b:Byte = EachIn data
			s:+ Chr(b)
		Next
		Return s
	EndMethod
	
EndType

...it seems to work.

-Henri


BlitzSupport2013
Hi Henri,

Many thanks for taking a look, that does indeed seem to work -- much appreciated!


Hardcoal2013
Josh , thanks for simplifying this


Hardcoal2013
since i dont know so much about networking ive started investigating josh code.

I would like to increase the commands in this example.
for example how do you check if a port is already occupied.
and how do you close a client.

Anyway ill get it one way or the other
its all matter of practice right.


Code Archives Forum