Best way to use IPCSocket between Console and Web App?

Hello All,
I have a console app and and web app. Both on the same computer. I want the Console app to send updates, or set flags for the Web App so that it performs certain operations.

My question focuses on the Web App side. My original plan was/is to create an instance in the Web App, App Section, then use events there to set or send updates to each existing Session object. A ‘one to many’ approach. However, while working on this, I thought that maybe there is some tech available that may be better suited so that the WebApp itself would not be taking on too much of a roll since it would have to loop through each session instance, and may have to make decisions as well, particularly when errors occur in the Socket.

The good news is, most of the time, the Web app just sits there and does nothing other than display info to the user. Very little to no user input - on a normal day-to day basis. But there will be times when for example reports will be run that may cause session usage to spike.

So my thought now is to ask if there is a way for each session to automagically receive each event that the Web App does without the use of a bunch of loops in the main app.

This is some of the code I started- perhaps someone has a suggestion to make it better, or if I am completely off base, advise best way to do this.
Thanks,
Tim

  WebSvrIPC_Socket = New IPCSocket
  AddHandler WebSvrIPC_Socket.Error, AddressOf WebSvrIPC_Err
  AddHandler WebSvrIPC_Socket.DataAvailable, AddressOf WebSvrIPC_DataAvailable
  AddHandler WebSvrIPC_Socket.Connected , AddressOf WebSvrIPC_Connected
  
Private Sub WebSvrIPC_DataAvailable(IPC As IPCSocket)
  
End Sub


Public Sub Manage_IPCSocket()
  If Pointer_Err > -1 Then 
      //OpenDriverError = 100
      //LostConnection = 102
      //NameResolutionError = 103
    
      //AddressInUseError = 105
      //InvalidStateError = 106
      //InvalidPortError = 107
      //OutOfMemoryError = 108
    
     For i As Integer = 0 To Pointer_Err
        If WebSvrIPC_LastErrCode(i) = 102 Then 
          WebSvrIPC_Socket.Flush
          WebSvrIPC_Socket.Connect
        Else   //If WebSvrIPC_LastErrCode(i) <> 102 Then 
        
        End If
      Next i
    
      Pointer_Err = -1  // Reset the Pointer
  End If
  
  
If Pointer_DtaAvail > -1 Then 
      For n As Integer = 0 To Pointer_DtaAvail
        For i As Integer = Self.SessionCount
                
         Next i
      Next n
      Pointer_DtaAvail = -1
  End If
End Sub


Private Sub WebSvrIPC_Connected(IPC As IPCSocket)
    IPC_IsConnected = True
End Sub


Private Sub WebSvrIPC_Err(IPC As IPCSocket)
    Pointer_Err = Pointer_Err + 1
    If Pointer_Err  > 10 Then Pointer_Err = 0
  
    WebSvrIPC_Err(Pointer_Err) = WebSvrIPC_Socket.LastErrorCode
    WebSvrIPC_LastErrCode = WebSvrIPC_Socket.LastErrorCode
End Sub

Private Property WebSvrIPC_Socket as IPCSocket
Private Property DataAvail(25) as String
Private Property IPC_Err(10) as Integer
Public Property IPC_IsConnected as Boolean = False
Private Property Pointer_DtaAvail as Integer = -1
Private Property Pointer_Err as Integer = -1
Public Property WebSvrIPC_LastErrCode as Integer

If you’re wanting to “push” the data out to the sessions, then this it one way to go. You could however store the data somewhere and have the sessions pull the data periodically instead to try to even out the load.

Just out of curiosity, why would running the report cause a session spike?

Hi Greg,
I have to show the console app polling other devices so their actions need to be as real-time as possible. Most of the data that is pushed to the sessions is setting a flag. They will check the flag status at some point in their code process, so effectively it would be a pull.

For the report, I am guessing that pulling the data and assembling the report will take more resources for the web app than simply displaying data and waiting. In practice, I have no real idea - will have to see.

Thanks for your reply.
Tim

Greg is right. Set the flag in App and have each session check that one flag via a timer. Or whatever loop is running. There’s really no difference between the session checking its local flag or checking a global flag. Whatever mechanism you are currently using can check one or the other just as well.

Thanks Tim,
That is probably a lot simpler!

Tim

And if all f the sessions are displaying the data in the same way, do that work once if you can.

Hi Greg.
The sessions are reloading/updating display charts, grids and a few colored objects. They would be the same. Is there a way to reload them all at once with one command? If so some sample code would be really appreciated!

Tim

I think he means, have App do the calculations and draw the charts, etc., into an image that the sessions can just display. That way any time consuming calculations/drawing only need to be done once instead of being repeated by each session.

OK, that makes sense. But how does the app “push” the new drawing/image to each of the sessions? How are they notified? Would that be like a App public property that each session pulls a copy of? This is a cool idea/concept but coding it seems a bit rough. Are there any samples to look at?

Thanks guys,
Tim

It’s not a “push”; the session checks periodically and pulls.

Yes.

As far as where the code resides, that’s really a refinement. Get it working with your flag first. Then evaluate how heavy the code is that each session uses to draw the results. If there’s a lot of processing going on, then it makes sense to move that code to App and have it pre-digest the data so each session does less work.

First thing, though, is you are simply moving one flag from Session to App.

You mentioned that in your current approach, the app was setting a flag in each session and the session was responding to that. How is that done now? Each session must be checking the flag periodically. You’ll do essentially the same thing, but there is only one flag (not one per session) and it resides in App.

Once you get that part working smoothly, then when you have App precalculate/pre-draw, the session will check the flag and respond to it by pulling the App variables that hold the results and spitting them out on the page.

Thanks Tim.

I got it working, but after doing so and thinking about it further, the simpler and better solution was to use a simple timer to read the database, which is shared between the two apps. The timer was used in both cases, but in the first case, an interval of 100mS was used. It was turned off while processing but proved to be far to resource intensive. Getting rid of the IPCSocket and just use a timer to check the database itself, with a reasonable interval of 2500mS for one set of actions and 250mS for another timer, which will likely be adjusted higher since a human could not detect the difference between that and some higher TBD number.

Anyway, I am testing with these then will look at moving those timers to the App instead of the MainPage (in my case).

Thanks again guys for your input!
Tim

Any update here, I want to do the same think but only that my console app will do some basic backup on some files and once done it will update a sqlite database , but I want to use the IPC sockets to send commands from the web app to the console app instead of using shell and pasting all the data publicly in the shell commands .

Now the next part comes I guess I can encrypt the commands and decrypt them on the console side and vice versa for the responses from the console app but how should I implement the IPCSocket on the console app ? build it dynamically in the Run Event or have it as a Class I guess from the Library and dumped on the project.

Doing that I guess the classes are set as global and in order to keep my code private I will have to subclass the IPCSocket and handle only the receiving part and sending part from the socket and all the processing within the private methods in the App side.

Would it be another way to do this safely ?

Thanks