Multiplayer client

A lot of ppl would like to have multiplayer functionality in blender but not too many are willin to work on it, so i propose a we start a community project. Anyone willin to help can do so.

Did this a month ago with lunarkignt, if anyone is interested in helpin out plz do, now since lunarknight is gone i need all the help i can get.
I will post an updated client in a few days. It will uses flags like in saluks multiplayer, then i should have movement done. I need some help creating a server. I had a server and it worked but it doesnt work under windows xp or linux so i am outta luck.

www.brainstorm-studios.net/Bruk/scripts/Client.blend

ill help with testing if you want.
i run 98 and xp.

ild like to help with coding but im still learning the socekt stuff in python, so maybe in a month or two when i know how.

I will help you if I can, i run WinXP on a 650 mhz and a 1,7 ghz. -If it’s very important I can fix a old 100 mhz to run win98.
I also have a old 200mhz machine with NT that I don’t use, but if it would be usefull I could prob. ‘set it up’ and make it run on my DSL-connection.

This morning I got an idea on how-to make LAN-multiplayer.
You could make a shared folder on the network, and then get blender to write the players position (or write every time the player moves) to a txt-file and then get blender to read the file with a VERY VERY VERY small interval… It works with the ‘3dchat’ (ASP/MySQL) i’m working on… (okey my chat’s running with a MySQL-database, but what ever…)
…Do you understand me?..

-Mads

i understood u. But it would be better if we use a client rather than a folder. Allot of teh math can be done server side before reaching the client (less time) Aswell when a player wants to move they need to send a request to the server to move the server oks it and tells all the other clients that clientaA moved to xxx postion. This will keep everything in sync. Aswell i have tried sending postions, it works but not well. When u play against someone else u just see them teliporting from one place to the next (when u send postions u need to send them at least 5 per second) this will produce alot of lag. So instead we should use flags. For example if the players movement flag is = to up then the player keeps going up until the flag changes. This way less data is sent.

I’ll help as much as possible owl. Heh, that shared folder thing is the first thing I tried way back when I got the crazy idea to make multiplayer. I think if we had someone who had networking experience there wouldn’t be much trouble getting it to work in blender. The ability is all there waiting, and python is extremely capable. It’s just none of us really have that much experience with things.

I think when I did multiplayer, my main snag was that my messaging system was too complicated. The messages had to be sent to all these different places, it was a mess. We need to work out a good messaging system, figure out how to integrate them on the blender side, as well as transform them into a network-compatible message (preferably taking as small amount of bandwidth as possible)

We also need an id system to make sure messages going over the network go to the right people and affect the right objects.

We need to decide what the server will be like: will it be a complete blender instance that is running, keeping track of all the objects, which sends the sync message when things get out of sync. Or will it be a python server which merely passes messages back and forth between clients and they try and sync things themselves. Either way, I think both the client and the server should be pure python or pure python+blender. This allows for most compatibility, and if we make a class for message reading, we can use that class easily in both the client and the server.

We need to work out a way to have forces, animation, or whatever all animate at the same speed on all computers. This is VERY important to minimise visible lag. If the server computer makes you move twice as fast as you do on your computer, you will appear to keep jumping forward constantly when moving. Whatever we use needs to be consistent and work for ipos, actions, and all manner of forces.

Before we do too much coding, we need to work out what kind of protocol we will use (related to the messaging system) and whether to use tcp/udp sockets, or whether to write it to support both.

And we also need to plan for utilizing multiplayer in blender games. We need a consistent and easy way to add new features to a multiplayer game without digging into the inner workings of the multiplayer code. In my old system, adding a new thing, like a command to make the character move forward, took several lines of really complicagted odd code, and it was extremely confusing.

I think the messaging system, id system, and protocol are the keys to our success, and with a LOT of planning before we code we can work out potential issues before they come up as well as make sure we’re all on the same page with where we are going.

Also, at each milestone, we need to be careful not to rush ahead and add a new feature suddenly, instead opting to test the current build as many ways possible. Maybe writing a testing strategy we can use for each version would be helpful.

I’m willing to help but I’m busy, so we either do it slowly or get some more people:)

Lets continue to discuss ideas for a while in this thread until we have some more concrete plans.

I think the messaging system, id system, and protocol are the keys to our success, and with a LOT of planning before we code we can work out potential issues before they come up as well as make sure we’re all on the same page with where we are going.

Also, at each milestone, we need to be careful not to rush ahead and add a new feature suddenly, instead opting to test the current build as many ways possible. Maybe writing a testing strategy we can use for each version would be helpful.

Thats the easy part(at least for me) so it wont be too much of a problem.
When a client recives a data it sends a message out … i dont feel like explaining the message system again, instead read the doc i made awhile ago about messaging http://68.7.28.252:8080/BBS/phpBB2/viewforum.php?f=9&sid=bff5c140a0bee137a13d817caa46730d
BTW its on a forum so u might have to register.

And we also need to plan for utilizing multiplayer in blender games. We need a consistent and easy way to add new features to a multiplayer game without digging into the inner workings of the multiplayer code. In my old system, adding a new thing, like a command to make the character move forward, took several lines of really complicagted odd code, and it was extremely confusing.

yes, If we have remoteplayer class , it would be better that way new features can be added by creating new functions. This has to be oop (object orientated programming) so that new stuff will be easy to impliment.I think this is my strong suite when it comes to programmig so its all good :slight_smile:

Also, at each milestone, we need to be careful not to rush ahead and add a new feature suddenly, instead opting to test the current build as many ways possible. Maybe writing a testing strategy we can use for each version would be helpful.

Ya, i agree. After each build we need tp do some bug squishing before we release the next one.

I’m willing to help but I’m busy, so we either do it slowly or get some more people:)

Its coo, i will try to find somemore people to help out. BTW i will be very busy until the 15th

I played around a bit. UDP actually seems a ton easier than TCP, because tcp servers have to listen() and accept() connections, while UDP only has to do the initial bind() and then anything can connect and send with ease.

Of course the loose nature of UDP could prove more difficult in the future.

The disheartening thing is that sock.connect(), sock.bind(), sock.listen(), and sock.accept() functions all only work on sockets that are connected. Because non-blocking errors if the function doesn’t complete instantly. So we basically have to use threading or some other mechanism (those things I dont really understand, select, semaphores, etc) at least on the server to keep making sure to get access to new players trying to connect.

On the client side however, we could live with it being blocked until you connect, once you are connected to the server we set non-blocking.

http://www.spinheaddev.com/downloads/dualsocket.py

:smiley: u cleaned up the dual sockets thnx. I guess i have the “ball” now?

The disheartening thing is that sock.connect(), sock.bind(), sock.listen(), and sock.accept() functions all only work on sockets that are connected. Because non-blocking errors if the function doesn’t complete instantly. So we basically have to use threading or some other mechanism (those things I dont really understand, select, semaphores, etc) at least on the server to keep making sure to get access to new players trying to connect.

Hmm. I dont really like using threads (partially cause i really dont get how to use them) I hope there is another way around it…
wouldnt this work?


bool = 0
counter = 0

while bool == 0 or counter < 5:
     try:
         socket.listen()
         bool = 1
     except:
         socket.setblocking()
         counter =  count + 1

After 5 failed tries it stops, or after one sucseful try i stops. This will aviod endless looping.
BTW i still dont understand why u commented out tcp.setblocking and udp… shouldnt they always be set to blocking. so those lines should be


self.tcp.setblocking(1)
self.udp.setblocking(1)

This way they are always set to blocking.

sorry, i didnt reead the your post carfuly, ignore the one above :expressionless:

I played around a bit. UDP actually seems a ton easier than TCP, because tcp servers have to listen() and accept() connections, while UDP only has to do the initial bind() and then anything can connect and send with ease.

Ya. udp is alot simpiler than tcp. Although they both have pros and cons liked we talked about yesterday. upd can be used for most of the stuff. tcp can be used for packets that must be delivered.
For anyone else wondering what the pros and cons for udp and tcp protocols here they are:

UDP
Pros-Easy to use
-Faster
-Will not get backlogged
Cons-Data is lost more easily than tcp
-Can only handle small amounts of data
- Not as secure at as tcp.

TCP
Pros-Can handle large amounts of data and even files
-Messages will not be lost as often as udp
-More secure
Cons-Harder to work with
-Messages get backlogged

And for anyone that was not on #gameblender last night and missed the discussion. We decided to make a dual socket socket class. Both with tcp and udp.

Anways, ill get working on some basic functions for dualsockets like…

closeall() # closes both tcp and udp connections
recvall()
udprecv()
tcprecv()

When your reached that time in the programming where the system work with simpel models, and you wan’t to try use it ‘in a real game’ i’m sure (you know, if it’s okey with Monkeyboi and all) you can borrow the ‘source’ for dark squad and try to implant it.

DARK SQUAD RULES!!.. oh, sorry :slight_smile:

-Mads

I made new version of dual sockets. There is very lengthy documentation in the modules doc string so please read that.
Here it is:

http://www.brainstorm-studios.net/Bruk/scripts/dualsocket.py"

BTW ZuiQ, sounds good. When we are done it should be so easy to impliment that most people that have some python experiance should be able to do it. Whats the point of having multiplayer if its too hard to impliment.

I updated it again :slight_smile: added some new functions and got rid of others. Check the doc string for updates.www.brainstorm-studios.net/Bruk/scripts/dualsocket.py . For those of you too lazy to download the code here it is

"""BDSocket module (Blender Dual Socket)

Message construction. A message is pretty much looks like this:

'["PACK:"message":ENDPACK"]'

"PACK" is used to determin the start ofa message.

"ENDPACK" is used to determin the end ofa message.

: is used for splitting the message.

message contains the id of the client that is sending it, the command, and the data. It would look something like this:

/id/command/data;data2;data3;

/ is used to seperate different feilds.

; is used to seperate data items so that more than one peice of data can be sent.

A package is a list of messages handled by tcp. Although it is not really a list, its a long string.



A.class Variables Section

1.Socket relatated Variables
	tcp
		The tcp variable is used to hold a tcp socket.

	udp
		The udp variable is used to hold a udp socket.

	tcpbuffer
		When a message is recived via tcp, the recvtcp() function stores it in the tcpbuffer.

	udpbuffer
		When a message is recived via udp, the recvudp() function stores it in the udpbuffer.
	

	tcpmessagequeue
		This is a list of messages that are waiting to be sent through tcp. Think of it like an
		outbox (like in ms outlook or other email aplications)
	

B.__init__ section
	init is used to set up BDsocket. It imports the socket class and makes a tcp and udp sockets.

C.Connection functions

1.connect(host,tcpport,udpport)
	This function connects both sockets. 3 Arguments can be passed; host, tcpport and udpport. If a socket is already connected 
	then it keeps the connection and connects the other socket. If both sockets are connected the connection function does nothing.

	host
		Used to set the host you want to connect to. For example; "http://wwww.blenderservers.org" or "68.5.72.3"
	
	tcpport
		Used to set the port that tcp will connect on. For example; 8080, 5012.

	udpport
		Used to set the port that udp will connect on. For example; 8080, 5012.

2.close()
	Closes both tcp and udp connections. (tcp.close() and udp.close() are socket functions please refer to the python socket
	module doc string if there is any or visit www.python.org)

D.Validation functions

1.check()
	This function checks to see if tcp and udp are connected. It returns a 2 dimensional array/list. The first value
	is if tcp is connected the second is if udp is connected.So:

	[1,1] == Both are connected.
	[0,0] == None are connected.
	[1,0] == Only tcp is connected.
	[0,1] == Only udp is connected.


E.Recv functions

1.recvtcp()
	This functions checks if there is any data in the tcp socket buffer to be recived (not to be confused with the class variable 
	tcpbuffer or tpcbuffer2), if there is then it saves it to the tcpbuffer class variable and returns the data recived.
	If not then it returns 0, aswell, if the the packet is not a legal packet it also will return a 0.

2.recvudp()
	Same as above except it saves it checks the udp socket buffer and then stores it in the udpbuffer class variable.

2.recvall()
	Calls recvtcp and recvudp. Then it returns a 2 dimensional array/list. First value is the tcp data, second is udp.
	If nothing is recieved it will return a 0 instead if data.If data is returned it can be used as a true value.

	[data,data] == Both sockets recived data.
	[0,0] == None recived data.
	[data,1] == Only tcp recived data.
	[0,data] == Only udp recieved data.

F.Send functions

1.sendpackage(data)
	Uses the socket send function to send data via tcp. Note that if you do not pass the data argument, the class variable
	tcpmessagequeue is sent.

2.sendmessage(data)
	Uses the socket send function to send data via udp. It also constructs a message before sending it.

G.Message construction functions

1.addmessage(message)
	Constructs a message and adds it to the tcpmessagequeue.

H.Message deconstruction functions

1.readpackage(data)
	Deconstructs all messages in the class variable tcpbuffer unless you pass an argument. After each message is deconstructed
	it is appended to the variable raw_message and raw_message is returned.

2.readmessage(data)
	Same as above but uses the udpbuffer as default, and since the udp buffer only contains 1 message at a time it only returns
	one raw message instead of a list of them.


"""





class BDSocket:

#*****************#
#*****************#
#class variables**#
#*****************#
#*****************#

#socket/message related	
	tcp = ""
	udp = ""	

	tcpbuffer = "" #used for recived messages
	udpbuffer = "" #used for recived messages

	tcpmessagequeue = [] #used for sending messages

#****************#
#****************#
#__init__********#
#****************#
#****************#

	def __init__(self):
	
		
		import sys	
		print "**Imported sys**
"

		#sys.path = ['c:\\python22','c:\\python22\\Tools\\idle','c:\\python22\\Lib','c:\\python22\\DLLs','c:\\python22\\Lib\lib-tk']
		#print "**Setting System Path**
"
		#print "**System Path set at:
"
		#print sys.path

		import socket
		print "**Imported socket**"

		#To send
		self.tcp = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
		self.udp = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
		print "**Setting socket protocols**
"		

##	I found out that connect statements dont work without blocking.
##	I think we can handle a little bit of a freeze when its connecting,
##	although we might have to resort to a thread for the server
##		self.tcp.setblocking(0)
##		self.udp.setblocking(0)


#*********************#
#*********************#
#connection functions*#
#*********************#
#*********************#

#Clients should connect
	def connect(self,host,tcpport,udpport):
		a = self.check()
		if not a[0]:
			print "Connecting TCP socket"
			self.tcp.connect((host,tcpport))
			#Turn off blocking here since we are connected
			self.tcp.setblocking(0)
		else:
			print "TCP Already Connected"

		if not a[1]:
			print "Connecting UDP socket"
			self.udp.connect((host,udpport))
			#Turn off blocking here since we are connected
			self.udp.setblocking(0)
		else:
			print "UDP Already Connected"


	#closes all connections
	def close()
		try:
			self.tcp.close()
		except:
			print "TCP is already closed"
		try:	
			self.udp.close()
		except:
			print "UDP is already closed"


#********************#
#********************#
#Valitade functions**#
#********************#
#********************#

	def check(self):
		t,u,tr,ur = 1,1
		try:
			self.tcp.getpeername()
		except:
			t=0		#TCP socket disconnected
		try:
			self.udp.getpeername()
		except:
			u=0		#UDP socket disconnected
		return t,u



#********************#
#********************#
#Recv functions******#
#********************#
#********************#

	#recvs data from udp, if a message is recived it returns the message and stores it in a buffer
	def recvtcp(self):
		a = self.check()
		if a[0]:
			try:
				data = self.tcp.recv()
				self.tcpbuffer = data
				return data
				
				
			except:
				return 0

	#recvs data from udp, if a message is recived it returns the message and stores it in a buffer
	def recvudp(self):
		a = self.check
		if a[1]:
			try:
				data = self.udp.recv()
				self.udpbuffer = data
				return data
			
			except:
				return 0
	#recvs all data
	def recvall(self):
		a = []
		tcpdata = self.recvtcp()
		udpdata = self.recvudp()
	
		a.append(tcpdata)
		a.append(udpdata)
		
		return a

#******************#
#******************#
#Send functions****#
#******************#
#******************#

	#sends data using tcp
	def sendpackage(self,data = self.tcpmessagequeue):
		try:
			self.tcp.send(str(data))
			self.tcpmessagequeue = ""
		except:
			print "TCP socket not connected"

	
	#sends data using udp
	def sendmessage(self,data):
		try:	
			message = '["PACK:"+data+":ENDPACK"]'
			self.udp.send(str(message))
		except:
			print "UDP socket not connected"


#********************************#
#********************************#
#Message construction functions**#
#********************************#
#********************************#

	def addmessage(self,message):
		 self.messagequeue+='["PACK:"+message+":ENDPACK"]'





#**********************************#
#**********************************#
#Message deconstruction functions**#
#**********************************#
#**********************************#

	def readpackage(self,package = self.tcpbuffer):
		temp = eval(package) #changes it into a list
		raw_messages = []
	
		for object in temp:
			temp2 = object.split(":")
			raw_messages.append(temp2[1])

		return raw_messages


	def readmessage(self,message = self.updbuffer):
		temp = message.split(":")
		return temp[1]

Sorry if its a bit messy i just copied and pasted.

I would also like to help with this where possible. I am a C++ developer and have done alot of UDP/TCP socket stuff at work.

However, I am a total newbie when it comes to games programming and python so not sure how much input I can give but I will try and help when I can.

Regarding UDP - if you don’t care whether a message has been received by the client or whether the connection is indeed still available then UPD is the choice to go for and very fast.

For example, a simple clock server sends the time every 10 minutes to it’s clients. It doesn’t care whether the client receives the time - it just continuously sends a new time every 10 minutes. Establishing a connection and waiting for a response would be a waste of time and resources. This is where UDP should be used.

I reckon for a network game TCP would be the best option because you are gonna need a reliable connection, and you are gonna need to know whether the link is still up or not.

I would also like to help with this where possible. I am a C++ developer and have done alot of UDP/TCP socket stuff at work.

:smiley: Thats just what we need. What we really needed was someone with socket experiance.

I think that most data should be sent with udp. Because if it was sent with tcp it gets backlogged and games get out of sync. Tcp should only be used for much larger amounts of data and data that must be recived. Since we are going to be use both protocols we are working on a dual socket class.

Well, we had the idea of using both udp and tcp, so we can send important messages with tcp, and less important messages with udp. So we have flexibility if we find that one type doesn’t work so well for somethings etc.

I think threads are ok, we just have to tread carefully and play with them within the blender environment to see what works and what doesn’t. They can be sticky, but I don’t see much of a way around it.

One thing I read said that you don’t want to keep sockets connected, because they are designed to connect, send, recv, and then close. So I’m not sure if we’ll handle that in BDSocket or in the client/server. If we keep it open, we have to make sure only to recv with the right amount of characters not to hit a spot where we recv and nothings there. Kind of sticky.

And Drum, you ought to be able to help us a lot. Neither of us are very experienced with network code, what little we know we’ve kind of stumbled around in. And the python socket code is basically just a wrapper for c++ sockets, so you probably know most of it:)

From what it seems, I think most games use UDP for speed issues, then do something like throw messages away if they come too late. I used tcp in my last try at multiplayer, and what seemed to happen was the messages built up and got overloaded, so the characters would be executing really old messages to catch up with what you are doing. Probably could design around it though.

Still so new at this…

Owl, my computer has the worm and I’m kind of busy, so you can work on it a bit longer.

:frowning: sorry to hear that saluk. Im not sure what else i can add to it.

Hello again everyone!

After my last post I decided to refresh my memory and look at all
my socket code at work. Also I looked at the dualsocket.py and it helped me alot with the python/python-sockets side of things.

I have a question about the list returned from check() in the dualsocket code. The comments state it is 2-dimensional. Is this a python convention? Is it just a list of 2-elements? If so then it is surely 1-dimensional? Or maybe I just don’t understand what’s going on!!!Anyway, just thought I would mention that because it confused me!!!

Also, I read in a previous post that you guys want to make the networking as object-oriented as possible. Therefore, I would like to propose a new version of dualsockets - keeping the basic code but re-organising it to use OOP.

Not sure if you guys are familiar/experienced with design patterns but I will babble away regardless!

Rather than using a list and doing everything twice, it would be more object-oriented to have two seperate classes then glue them together with a third class. I propose maybe using the STRATEGY pattern or DECORATOR pattern to acheive this. These patterns are just a way
of acheiving the same thing as the list in check() except it will be
extendable and easier to understand (from an OOP point of view!).

I will be able to write a demonstration and explain further about my idea but it may take a few days as I am gonna have to figure out how to do it
in python.

Before I go ahead, just wondering what everyone’s thoughts are. The dualsockets code is fine as it is and it may not be worth changing it (and potentially complicating it) unless you guys agree with me that the more extendability/reusability the better.

Thanks for the post Drum. The thing in the check makes use of pythons packing/unpacking of lists capability. You can return multiple values by seperating them into commas. It basically turns that into a list and returns it. Then on the other end, you can unpack a list into a list of variable names. Each variable seperated by commas gets the value of the list at that point.

return 0,1,2,3
is the same as
return 0,1,2,3

x,y,z,f = [0,1,2,3]
is the same as
x = 0
y = 1
z = 2
f = 3

So you can return a list and unpack it into several variables.

Yeah, I think object oriented might be the right way to go. In fact I’m not sure if we really need the dualsocket code at all, rather a udpsocket and a tcpsocket module and use them both in the server and class. But I’m not really sure how to go about it.

I have a question about the list returned from check() in the dualsocket code. The comments state it is 2-dimensional. Is this a python convention? Is it just a list of 2-elements? If so then it is surely 1-dimensional? Or maybe I just don’t understand what’s going on!!!Anyway, just thought I would mention that because it confused me!!!
[/quote]

a = [0] <– 1 dimensional array
a = [0,0] <– 2 dimensional array

In python arrays are called lists. If its 2 dimensional then that means it contains 2 “elements” (not sure if that is the right word). If it is 1 dimensional then it contains 1 element. Sorry if it confused you :frowning:

Rather than using a list and doing everything twice, it would be more object-oriented to have two seperate classes then glue them together with a third class. I propose maybe using the STRATEGY pattern or DECORATOR pattern to acheive this. These patterns are just a way
of acheiving the same thing as the list in check() except it will be
extendable and easier to understand (from an OOP point of view!).

I’m not sure about the patterns STRATEGY and DECORATOR. Perhaps I am not as familiar with OOP as i though i was. But go ahead. Write a demonstration. I think this project should be as object orientated as possible. Perhaps you can explain to me why we need 3 classes, I am not sure why you would split the dualsocket into 3.

Thanx for your quick replies Saluk and Blender_owl.

Regarding the check() function, in C++ a 2-dimensional array is like a table with columns and rows (or a matrix in 3d maths).

this is a table 10x10 which is 2-dimensional:


char list[10][10]  

this is a one-dimensional list of 10 elements:


char list[10]

Is it the same in python?

Saluk said this:

Yeah, I think object oriented might be the right way to go. In fact I’m not sure if we really need the dualsocket code at all, rather a udpsocket and a tcpsocket module and use them both in the server and class. But I’m not really sure how to go about it.

I would say that the dualsocket code is fine except it is not very extendable or re-usable. What if you wanted to add another protocol other than UDP or TCP? You would have to go through the code and change every function. The question is - would it EVER be feasible to have more protocols than UDP or TCP, or maybe a different implementation of UDP, TCP at some stage in the future? If not, then there’s not much point in complicating the code with OOP. If the answer is yes then we need to modify the code which brings me nicely to blender_owls question!

I’m not sure about the patterns STRATEGY and DECORATOR. Perhaps I am not as familiar with OOP as i though i was. But go ahead. Write a demonstration. I think this project should be as object orientated as possible. Perhaps you can explain to me why we need 3 classes, I am not sure why you would split the dualsocket into 3.

Forget the DECORATOR, sorry about that! But using the Strategy design pattern we can provide a class that supports UDP and TCP and it will be easy to add new protocols if ever we want to!

For more info about the pattern type “Strategy Design Pattern” into Goggle and you will get loads of info. Design Patterns are just a way of tackling well-known problems in an object-oriented way and for our problem the Strategy is perfect.

Put simply we can have a Connection or Link class (or something) that provides the interface. link.send() link.receive(), etc. The link class contains a reference to a protocol which is initialised when the object is created. All methods, such as send() and receive() delegate to the protocol:


class Link:
   def __init__(self, protocol)
       self.protocol = protocol
      
   def send(self)
       protocol.send()

   def receive(self)
       protocol.receive()

protocol is a reference to the Protocol class which is the interface for the different protocols:


class TCPSocket(Protocol)
   def send(self)
       #send a tcp socket here

class UDPSocket(Protocol)
   def send(self)
       #send a udp socket here

All the client would do is this:


udpSocket = UDPSocket

link = Link(udpSocket)
link.send(data)

or to get the dualsocket behaviour:


sockets = [ UDPSocket, TCPSocket ]

sockets[0].send(data)  #send udp
sockets[1].send(data)  #send tcp

Sorry about my python - its crap. Hope you can understand it!

Although it may sound quite over the top it is actually quite simple to use in practise because all coding is done in logical black boxes. To receive a UDP message, add code to UDPSocket.receive(). To connect to a TCP socket, add code to TCPSocket.connect().

Also, it is extendable. We could add a SerialComms protocol and write the send, recevie, connect, close methods and it would work without chaning any existing code.

I will get my python book out and start learning it properly (I am reading lots of books and learning it well, but not wrote any scripts yet as you can probably tell!). Over the weekend I will try to get version working and let you guys know how I go on. In the meantime, any thoughts?