About Monkey 2 › Forums › Monkey 2 Programming Help › Server question?
This topic contains 10 replies, has 4 voices, and was last updated by
SamFisher 1 year, 5 months ago.
-
AuthorPosts
-
October 21, 2017 at 8:11 pm #11269
When looking at the echoserver.monkey2 file I see that the server doesnt have a stream is this an oversight?
I ask as in all networking sometimes messages need to be sent to the server but from this the server doesnt have any way to receive them. I tried attaching a SocketStream to a socket that is listening but all I get is spammed with:
socket_recv error! err=10057, msg=Unknown error, socket=1244, data=00e50184, size=4Does anyone have a more concise networking example maybe a simple chat system as the echoserver.monkey file doesnt actually show client/server systems as it appears that the client just spams its stream with data and gets it back again which is the effect I am getting now.
October 22, 2017 at 4:32 am #11274If you’re talking about TCP, a ‘listening’ server socket is not a stream – it is a ‘connection point’ for incoming connections (which are themselves streams). With TCP, you need to be connected before you can send/receive data so you can’t actually exchange any data with the ‘server’ which is there purely to establish the connections.
With UDP you can talk to the ‘server’ (a ‘server’ doesn’t actually do much/anything) but it is unreliable and packets can arrive out of order so it’s not as easy to use as TCP.
If you’re thinking about using something higher level, I was thinking about converting enet again which would be very easy to do. Would this be useful?
There is also raknet, which is much more complex and would likely take considerably longer to do fully:
http://www.jenkinssoftware.com/raknet/manual/Doxygen/
Both are very mature and well regarded.
If you want to keep using sockets, I recommend looking at some socket tutorials first, eg:
https://www.tutorialspoint.com/unix_sockets/
A lof of these use threads to handle multiple connections, but the basic ideas are the same with fibers. Google for more etc…
October 22, 2017 at 5:47 am #11282If ENet had Max like functionality and ipv6 I would be very interested in that, from what I can gather though it’s still only ipv4. There is a bodge patch to make it use ipv6 but it’s reliability is questionable.
If servers are just connection management then I will just reconfigure the code I have to make it work like that.
One thing that puzzled me is I had two clients connected but both were receiving what they sent through the stream which is why I wondered if it was actually connected or was just bouncing back. I will dig deeper and try to adjust the echoserver code to see if I can get a example of the issue.
October 22, 2017 at 10:26 am #11285OK after giving this a lot of thought (yes my head hurts after all that lol) a way around it would be to give the server it’s own client (id0) this means basically the connection server will be able to send messages to clients etc.
It’s a nice theory and one I will now try to put into practice
October 22, 2017 at 11:25 am #11286I know it’s OT but that’s the way the AGK guys handle it. When creating a server there, you will have client ID 0 instantly as well on the server side.
October 22, 2017 at 11:34 am #11287Thanks Voidwalker at least I know it’s how some other systems do it :).
What I want to make is a easy to use robust network system for MX2 that way anything else will be easier when dealing with Internet/networking stuff.
October 22, 2017 at 11:45 am #11288I will give this a try as well and will share my results. Maybe we can create some simple server client app for the bananas folder.
October 22, 2017 at 2:34 pm #11289Good idea, we could make a simple chat program that could work with multiple clients. At least that way it could replace the echoserver.monkey file giving a better example
October 22, 2017 at 2:57 pm #11290Yep, definitely. But I would wait for 1.1.08 because Mark changed quite a lot under the hood. Will see that I pull the github stuff and compile it by myself but the last time I tried (last week) it could not compile all modules because there were some breaking changes.
October 22, 2017 at 3:28 pm #11291OK will wait for 1.1.0.8
October 25, 2017 at 10:33 pm #11320Little late, but here a little Chat Server/Client App for 1.1.07
Server.monkey2
Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153Namespace serverChatSample#import "<std>"#import "<mojo>"Using std..Using mojo..Const HOST:="localhost" 'Note: Use "" for 'public' host?Const PORT:=40122Class ServerDemoMethod New()New Fiber( Server )EndMethod Server()Local server:=Socket.Listen( HOST,PORT )If Not server Print "Server: Failed to create server" ; ReturnPrint "Server @"+server.Address+" listening"server.SetOption( "SO_REUSEADDR",1 )server.SetOption( "TCP_NODELAY",1 )RepeatLocal socket:=server.Accept()If Not socket ExitPrint "Server accepted client @"+socket.PeerAddressLocal stream:=New SocketStream( socket )New Fiber( Lambda()RepeatLocal line:=stream.ReadSizedString()Local command:StringLocal _var1:StringIf Not line ExitPrint line+" from client @"+socket.PeerAddressIf(line.Contains("/_join_ "))ThenNew Client(line.Replace("/_join_ ",""),socket,stream)line=""Endifif(line.Contains("/"))ThenLocal c:string[]=line.Split(" ")Print c.LengthIf(c.Length>1)command=c[0]_var1=c[1]Endifline=""EndifIf(command)line=""Select commandCase "/nick"line="***"+Client.ReturnUserName(socket)+" is now known as "+_var1Client.ChangeUserName(socket, _var1)Defaultline="WRONG COMMAND"End SelectEndifIf(line)if(command)command=""_var1=""Elseline=Client.ReturnUserName(socket)+": "+lineEndif'Sending to allFor Local c:Client=Eachin Client.clientListc.clientSocketStream.WriteSizedString(line)NextEndifForeverstream.Close();Print "Stream Closed"End )ForeverPrint "Server:Bye"server.Close()EndEnd'Client ClassClass ClientField clientSocket :SocketField clientName :StringField clientSocketStream :SocketStreamGlobal clientList :List<Client> = New List<Client>Method New(name:String, socket:Socket, stream:SocketStream)Self.clientSocket=socketSelf.clientName=nameSelf.clientSocketStream=streamclientList.AddLast(Self)EndFunction ReturnUserName:String(socket:Socket)For Local c:Client=Eachin Client.clientListif(c.clientSocket.PeerAddress=socket.PeerAddress)Then Return c.clientNameNextReturn "Anonymous"EndFunction ChangeUserName(socket:Socket, newName:String)For Local c:Client=Eachin Client.clientListif(c.clientSocket.PeerAddress=socket.PeerAddress)Then c.clientName=newNameNextEndEnd'--MainFunction Main()New AppInstanceNew ServerDemoApp.Run()EndClient.monkey2
Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142Namespace clientChatSample#Import "<std>"#Import "<mojo>"#Import "<mojox>"Using std..Using mojo..Using mojox..Const HOST:="localhost" 'Note: Use "" for 'public' host?Const PORT:=40122Class ClientDemo Extends WindowGlobal sendLine :StringGlobal firstrun :BoolGlobal mainView :DockingViewGlobal chatView :TextViewGlobal inputField :TextFieldGlobal sendButton :ButtonGlobal stream :SocketStreamGlobal client :SocketMethod New()Super.New( "Client Chat Sample", 800, 600, WindowFlags.Resizable )'----chatView=New TextViewchatView.ReadOnly=TruechatView.Text="Commands without quotes:~n'/exit' Terminate the Chat Client~n'/nick newUserName' Change the UserName~n"inputField=New TextFieldinputField.Text="user"+Millisecs()'Randome User NamesendButton=New Button("Send")'----mainView=New DockingViewmainView.AddView(chatView,"top","90%")mainView.AddView(inputField,"left","90%")mainView.AddView(sendButton,"right","10%")Local sendLineLambda:=Lambda()sendLine=inputField.TextinputField.Text=""'chatline CommandsSelect sendLineCase "/exit" 'Terminate AppApp.Terminate()End SelectIf Not(firstrun)New Fiber( Client )EndifEnd'----sendButton.Clicked=Lambda()sendLineLambda()End'----inputField.Entered=Lambda()sendLineLambda()EndContentView=mainViewEndMethod Client()Local receiveLength:IntchatView.AppendText("Client: Try to connect to Server("+HOST+":"+PORT+")~n")Fiber.Sleep( .5 )client=Socket.Connect( HOST,PORT )If Not client'Print "Client: Couldn't connect to server"chatView.AppendText("Client: Couldn't connect to server~n")ReturnEndif'Print "Client @"+client.Address+" connected to server @"+client.PeerAddresschatView.AppendText("Connected to server @"+client.PeerAddress+"~n")client.SetOption( "TCP_NODELAY",1 )stream=New SocketStream( client )Repeatif(sendLine)If not(firstrun)stream.WriteSizedString("/_join_ "+sendLine)firstrun=TrueElsestream.WriteSizedString(sendLine)EndifsendLine=""Endifif(receiveLength<client.CanReceive)chatView.AppendText(stream.ReadSizedString()+"~n")receiveLength=client.CanReceiveEndifFiber.Sleep(.01)ForeverPrint "Client:Bye"stream.Close()EndEnd'--MainFunction Main()New AppInstanceNew ClientDemoApp.Run()End -
AuthorPosts
You must be logged in to reply to this topic.