Code archives/Networking/UDP Networking Class
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
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
| ||
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() |
| ||
Looks handy, thanks. |
| ||
Very clever and streamlined. So how many players could this handle without threading? |
| ||
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: |
| ||
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! |
| ||
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 |
| ||
Hi Henri, Many thanks for taking a look, that does indeed seem to work -- much appreciated! |
| ||
Josh , thanks for simplifying this |
| ||
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