simple network functions

BlitzMax Forums/BlitzMax Beginners Area/simple network functions

Bremer(Posted 2008) [#1]
I have no experience with network code at all, and I am looking for some library or other that would enable me to add network communication between a server and perhaps up to 10 clients.

Its for a turn based game, where the server will do some calculations based on dice rolling and then tell the client the outcome. The client informs the server about what the user is doing.

I do not think, that it will envolve a lot of traffic, but since I have no knowledge about how networking works, I am hoping that someone can offer some advise and point me in the right direction towards something that is easy to implement and will not require prior knowledge other than knowing how to code generally.

I am fairly knowledgeable when it comes to bmax, I just have not touched anything to do with networking.


DrDaxxy(Posted 2008) [#2]
Maybe this could help you:
http://blitzmax.com/codearcs/codearcs.php?cat=4&order=&asc=&lang_id=2


Retimer(Posted 2008) [#3]

Its for a turn based game



I suggest blitzmax socket streams then. They are very easy to use, and is perfect for use in turn-based games, however, not with mmo or fps.


Bremer(Posted 2008) [#4]
I don't really know what I am doing with this network stuff.

Here is what I have so far, but its not really working, and I am a bit clueless as to what I am doing wrong.

TYPES:
Type TServer

	Field socket:TSocket
	Field port:Int

	Function Create:TServer(port:Int)
		Local server:TServer = New TServer
		server.socket = CreateTCPSocket()
		' check to see if a socket was created, and if not return null otherwise return server
		If Not BindSocket(server.socket, port) Or Not SocketListen(server.socket) Then
			CloseSocket(server.socket)
			Return Null
		End If
		server.port = port
		Return server
	End Function
	
	Method close()
		CloseSocket(socket)
	End Method

	Method accept:String()
		Local message:String = ""
		Local clientname:String = ""
		Local client:TSocket = SocketAccept(socket)
		If client Then
			Local stream:TSocketstream = CreateSocketStream(client)
			clientname = DottedIP(SocketRemoteIP(client))+":"
			While SocketReadAvail(client)
				message :+ ReadLine(stream)
			Wend
			Return clientname+message
		Else
			Return Null ' no connection made
		End If
	End Method 

End Type

Type TClient
	Field host:String
	Field port:Int
	Field socket:TSocket
	Field stream:TSocketstream
	
	Function Create:TClient(host:String,port:Int)
		Local client:TClient = New TClient
		client.host = host
		client.port = port
		client.socket = CreateTCPSocket()
		ConnectSocket(client.socket,HostIp(host),port)
		If client Then
			client.stream = CreateSocketStream(client.socket)
			Return client
		Else
			Return Null	' no luck creating client
		End If
	End Function
	
	Method send(message:String)
		WriteLine(stream,message)
	End Method
	
	Method recieve:String()
		If SocketReadAvail(socket) Then Return ReadLine(stream)
	End Method
End Type


SERVER:
SuperStrict

Import brl.stream
Import brl.socket
Import brl.socketstream

Include "servertype.bmx"

AppTitle$ = "SERVER"
Graphics 320,240,0
SetClsColor 128,128,128

Local server:TServer = TServer.Create(112233)
Local mess:String

Repeat

mess = server.accept()

Until KeyHit(KEY_ESCAPE) Or AppTerminate() Or mess <> ""

Cls
DrawText mess,0,0
Flip

WaitKey

End


CLIENT:
SuperStrict

Include "servertype.bmx"

AppTitle$ = "CLIENT"
Graphics 320,240,0

Local client:TClient = TClient.Create("127.0.0.1",112233)

If Not client Then End

While Not KeyHit(KEY_ESCAPE)
	If KeyHit(KEY_SPACE) Then client.send("Test")
Wend


I really appreciate any help I can get with this.

What I would like to be able to, is to transmit messages between clients and server, where the server knows which client who sent the message, and it can react on this message and send a response back to the correct client.


Dreamora(Posted 2008) [#5]
Well, TCP is a stream so per stream there is only one "place to come from". Just store the IP when you accept the connection in a datastructure that is meant to hold playername, ip and whatever else you might like (most likely you use a TMap and use the IP in as string as key to retrieve it. the object you put in would be your own TPlayer type or whatever you want to call it)


Bremer(Posted 2008) [#6]
This is probably the first time, where I have been at a loss with bmax, and up until now I have been able to live with the really poor documentation that comes with it. But that has been because the other things I have used bmax for, has been things where I have had prior knowledge.

Networking is something I know absolutely nothing about, so I am starting with a clean slate. And now I really see why it really hinders people when the documentation contains absolutely no examples at all.

How are someone to know where to begin when there are no info to read into. I really think that they should take a month or two out of what ever they are working on and write some useful examples. It would really make it a much easier language to dig right into and they would probably gain a lot of new users.

But since that is unlikely to happen, I am left with the hopes that other users on this forum is kind to help or work my way through a lot of hours of trial and error.


Dreamora(Posted 2008) [#7]
Socket information within BM would be worthless.
Simply because different restrictions and capabilities are bound to them depending on the OS you use them on.
So you will have to look for OS dependent informations on them, there is no general information that will help you working with them.
That will most likely explain as well why most do not attempt Sockets but prefer existing networking libraries.
Its definitely not easy if you have 0 technical background in that area and you will take quite some time (several months most likely) till you learned the ins and outs

Hope that explains why BM has no informations on the sockets. It would be worthless, its not a language feature, but an OS one

BM offers streams and GNet to use networking. Both are definitely better suited. GNet is little documented, but the networking streams work the same as the regular ones beside the connection part and are documented.

You at best start out with them and read up on how you transfer information between different clients or client - server (like stuff on how such a message is structured with the MessageID and the like).
Thats stuff not related to the networking but to your own network handling code within your application and therefor not documented as well as it has nothing to do with BM.

BM takes care that the information is sent from A to B
What you send, when you send it and how it is structured is up to you and there are many different pages on this topic


Bremer(Posted 2008) [#8]
I have spent some time looking at that GNet, and I have come up with the following, which works as far as sending information to the server. But what if there are more than one client contacting the server. How would I go about changing it so that it can know who is sending the data?

Server:
SuperStrict

Local host:TGNetHost = CreateGNetHost()
Local port:Int = 1234
Local address:String = "127.0.0.1"
Local timeout_ms:Int = 10000

Local listen:Int = GNetListen( host, port )
If Not listen Then RuntimeError "GNetListen failed"

Local remoteObj:TGNetObject
Local objList:TList = New TList

Local txt:String[32]
Local num:Int[32]

Graphics 320,240

While Not KeyHit(KEY_ESCAPE)

	Delay 10

	GNetSync host
	
	objList = GNetObjects( host, GNET_MODIFIED )
	For remoteObj = EachIn objList
		DrawText GetGNetString( remoteObj, 0 ), 10,10
		DrawText GetGNetString( remoteObj, 1 ), 10,20
		DrawText GetGNetString( remoteObj, 2 ), 10,30
		DrawText GetGNetInt( remoteObj, 3 ), 10,40
		DrawText GetGNetInt( remoteObj, 4 ), 10,50
		DrawText GetGNetInt( remoteObj, 5 ), 10,60
		DrawText GetGNetInt( remoteObj, 6 ), 10,70
	Next
	Flip
	
Wend
CloseGNetHost(host)
End


Client:
SuperStrict

Const GNETSLOT_NAME:Int = 0
Const GNETSLOT_STATS:Int = 1
Const GNETSLOT_VITALS:Int = 2
Const GNETSLOT_LOCALMAPX:Int = 3
Const GNETSLOT_LOCALMAPY:Int = 4
Const GNETSLOT_WORLDMAPX:Int = 5
Const GNETSLOT_WORLDMAPY:Int = 6

Local host:TGNetHost = CreateGNetHost()
Local port:Int = 1234
Local address:String = "127.0.0.1"
Local timeout_ms:Int = 10000

Local connect:Int = GNetConnect( host, address$, port, timeout_ms )
If Not connect Then RuntimeError "GNetConnect failed"

Local localObj:TGNetObject = CreateGNetObject:TGNetObject( host )

Graphics 480,360

While Not KeyHit(KEY_ESCAPE)

	Delay 10

	GNetSync host
	
	If KeyHit(KEY_SPACE) Then
		SetGNetString localObj,GNETSLOT_NAME,"Character Name"
		SetGNetString localObj,GNETSLOT_STATS,"18,9,16,11,13,10"
		SetGNetString localObj,GNETSLOT_VITALS,"108,32"
		SetGNetInt localObj,GNETSLOT_LOCALMAPX,100
		SetGNetInt localObj,GNETSLOT_LOCALMAPY,100
		SetGNetInt localObj,GNETSLOT_WORLDMAPX,0
		SetGNetInt localObj,GNETSLOT_WORLDMAPY,0
	End If
	
Wend
CloseGNetHost(host)
End


I was thinking that I could use the first slot of the object and use the player character name and then react to that. But I am not sure about what to do when having to send data back to the clients.

I am going to keep working on this and hopefully I will get some working code that will allow me to continue with the game idea. I just think that I need to have working network communication done before I move on.

Any input on effective ways of dealing with this is highly welcome.


Dreamora(Posted 2008) [#9]
You don't send data back on the same object.
As for the other objects: when the player logs in on the server, create a local object there. This will then exist as remote object on the clients side. This has the very nice side effect that other clients can manipulate anything but their own beeing.
You then only need to syncronize the local object and the corresponding client remote object and you are done.

The alternative is to use the messaging system to send messages back to the player.

As for easy retrieval of the gnet object of a given player: brl.map -> TMap and using the name as key.


Trader3564(Posted 2008) [#10]
Isn't GNet Win32 only? Or was that GNetEx?


Dreamora(Posted 2008) [#11]
there is no GNetEx at all.

GNet is crossplattform and uses Pub.ENet as networking core. No problem with other platforms


Ked(Posted 2008) [#12]
I have no experience with network code at all, and I am looking for some library or other that would enable me to add network communication between a server and perhaps up to 10 clients.

Its for a turn based game, where the server will do some calculations based on dice rolling and then tell the client the outcome. The client informs the server about what the user is doing.

I do not think, that it will envolve a lot of traffic, but since I have no knowledge about how networking works, I am hoping that someone can offer some advise and point me in the right direction towards something that is easy to implement and will not require prior knowledge other than knowing how to code generally.

I am fairly knowledgeable when it comes to bmax, I just have not touched anything to do with networking.


My BBStream Module might help with what you are requesting.


Bremer(Posted 2008) [#13]
I would prefer to use open code, not a module. There is just no way of knowing what is in the module code, and there is no way of making changes to the code within the module. Also, often with updates to bmax modules break and doesn't work anymore, and if for some reason the module becomes unsupported, then your are out of luck.


Ked(Posted 2008) [#14]
I would prefer to use open code, not a module. There is just no way of knowing what is in the module code, and there is no way of making changes to the code within the module. Also, often with updates to bmax modules break and doesn't work anymore, and if for some reason the module becomes unsupported, then your are out of luck.

Just suggesting.


Bremer(Posted 2008) [#15]
Yeah, I know and thanks for the suggestion. It looks like your module has all the bases covered, but for the above mentioned reason, its probably not for me. Its for a small sparetime project, so its not time critical, I can take my time getting to know what is needed, but I do wish it would have been easier than it appears to be.


Ghost Dancer(Posted 2008) [#16]
I created the following code for a turn based game:

http://blitzmax.com/codearcs/codearcs.php?code=1908

It uses GNet so no external modules are needed. Is that may be of use to you?


Bremer(Posted 2008) [#17]
Thanks, I will take a look at it.