I am trying to create a console app with a udp socket in XOJO 2013R2 and encountering difficulty. I create a console app and from the IDE Library I drag a UDPSocket to the Contents an name it UDPSocket1. It has no methods or event handlers exposed in the IDE.
I found I am able to rightlclick and add empty methods for Close,Connect,Read,Write and I also can add a Property for Port and similarly add an event handler for DataAvailable. The ide intellisense seems to understand all the methods and properties of the socket so etc.
But I get compile time errors of UDPSocket1.Write(…) This item does not exist and d=UDPSocket1.Read This item does not exist…
It ‘feels’ to me like Im not correctly inheriting the methods and properties of the UDPSocket class or perhaps its interface etc.
Can anyone tell me what Im doing wrong??
In the App.Run I have:
Dim UDPSocket1 as UDPSocket
UDPSocket1 = new UDPSocket
UDPSocket1.Port = 54003
UDPSocket1.Connect
Dim UDPSocket1 as UDPSocket
UDPSocket1 = new UDPSocket
UDPSocket1.Port = 54003
UDPSocket1.Connect
Dim myTimer as new Timer
myTimer.mode = Timer.ModeMultiple
myTimer.Period = 5000
All a matter of scope
App.Run creates a local variable (called UDPSocket1) that IT can reference in that method
But that socket does not exist elsewhere so the Timer has no clue what UDPSocket1 IS or what it might be able to do
I have no idea how experienced a developer you may be so …
The User Guide Fundamentals has a section about this (page 71 or so)
As does the Introduction to Programming Book (page 115) available here http://xojo.com/download/extras.php
I guess my problem is figuring out how to get UDPSocket1 instance in scope. This seems quite different from a windowed app.
For a windows app I just drag an UDPSocket to the navigation area and name it UDPSocket1 and its methods and events are automatically visible and ‘in scope’. Not so with a console app project. The methods and events do not seem available to me.
I did just try creating a Property of the App named Socket1 of type UDPSocket and it appears to solve the scope issue, but then I am unable to create things like EventHandlers such as DataAvailable for it.
There is clearly some step I am omitting between adding an UDPSocket class in-scope instance to my project and then having it expose its properties, method and events to the IDE. I have been scouring the new docs and examples but info on console apps seems sparse. Any help or example would be a huge help.
Instead of trying to drag one onto the project, add a property of app or a module, and instantiate the socket in app.run. Use AddHandler to tie the events to methods of your project.
Thanks all! It works now… but could someone educate and advise…
Socket1 is now a property of App of type UDPSocket
Below is my abbreviated code should someone else pass this way.
I still have a couple of questions that would help with my education. Everywhere I reference Socket1 I seem to need to predicate it with either “App.” or “me.” such as in App.run and myTimerAction handler as shown below…
apparently I dont ‘need’ to predicate Timer1 with “me or App” because its only actually referenced within scope of App so it doesnt even really need to be a Property of app… which implies to me that creating property of an object in app is just really just ‘declaring a variable’ as I still have to instantiate it with a “new” at startup
is there any difference between use of “App.” and “me.” syntax or am I headed towards any problems? What is recommended practice/style or am I still missing something here?
Thanks for the great assistance! - Rich
in:App.run
Dim Socket1 as UDPSocket
me.Socket1 = new UDPSocket
me.Socket1.Port = 0
me.Socket1.RouterHops=32
AddHandler me.Socket1.DataAvailable, AddressOf socket1DataAvailable
AddHandler me.Socket1.Error, AddressOf socket1Error
me.Socket1.Connect
if NOT me.Socket1.IsConnected then
stderr.WriteLine(“socket failed to connect”)
return 0
end if
Dim Timer1 as Timer
Timer1=new Timer
Timer1.mode = Timer1.ModeMultiple
Timer1.Period = 2000
AddHandler Timer1.Action, AddressOf myTimerAction
Do
App.DoEvents
Loop
’ Quit
Return 0
and in: myTimerAction(sender as Timer)
Dim dg as Datagram
dg = new datagram
dg.address=“192.168.0.5”
dg.Port = 54003
dg.Data = “getmesomedata”
me.Socket1.Write(dg)
and in: sock1DataAvailable(sender as UDPSocket)
Dim d as new Datagram
Dim s as string
d=sender.Read
s=d.Data
stderr.WriteLine( s )
That creates a local variable, which is why you have to use “me” or “app” to get to the real socket. With that line in place,
Socket1.xxx refers to the local instance which is not available to the timer
me.Socket1.xxx refers to the property of App, which IS available to the timer.
If you remove the Dim line, then Socket1.xxx will refer to the App property directly.
Personally I’d subclass UDPSocket & implement the events in the subclass
Then in my app I instantiate that as you’ve done for the UDP Socket & not have to worry about add handler at all
Then at least the events & the class they belong to are even physically close to each other in the code
AddHandler is not something you generally want to use for everything - it just makes for modern spaghetti code.
For narrowly targeted tasks it works well but it’s not a “design pattern”
You have to worry about calling RemoveHandler on instances you’ve added handlers too. Otherwise nobody else will ever be able to call AddHandler for that event again (multiple handlers aren’t supported at this time).
And you will want to read up on how reference counting comes into play with AddressOf, delegates, and AddHandler: http://support.realsoftware.com/listarchives/realbasic-nug/2011-03/msg01193.html
I agree with Norman on making a subclass as a general approach. Your example is simple enough now, but as it becomes more complex, you should explore subclasses.