It is currently Fri Feb 21, 2020 1:56 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 12 posts ] 
Author Message
 Post subject: UDP Local Network Short Text Sending (All OS)
PostPosted: Fri Dec 13, 2019 11:59 am 
Offline
Addict
Addict
User avatar

Joined: Fri May 12, 2006 6:51 pm
Posts: 2225
Location: Germany
After a request here now the cleaned version to send short string between programs over UDP.

The strings are sent with STX and ETX to ensure that the string is complete. The string is passed to the program via PostEvent. For this the string must be fetched with the function FreeString, so that the memory is released.

The resources are automatically cleaned up after 5 minutes so that it does not lead to a memory leak.

Each program gets its own port. e.g. Port 2001, 2002, etc.

Update v1.02
- Added InitUdpServer(...)
- Added SendStringEx(...) for sending string over LAN
- Added ClearConnection() for release all SendString resources (Threaded)

Update v1.03
- Small Bugfix: Clear Client Map

Update v1.04
- Small optimizations

Update v1.05
- Bugfix PeekS

File UdpServer.pb
Code:
;-TOP

; Comment : UDP Local Network Short Text Sending
; Author  : mk-soft
; Version : v1.05

CompilerIf #PB_Compiler_Thread = 0
  CompilerError "Use Compileroption Threadsafe!"
CompilerEndIf

EnableExplicit

;-- MacOS NapStop

CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
  ; Author : Danilo
  ; Date   : 25.03.2014
  ; Link   : https://www.purebasic.fr/english/viewtopic.php?f=19&t=58828
  ; Info   : NSActivityOptions is a 64bit typedef - use it with quads (.q) !!!
 
  #NSActivityIdleDisplaySleepDisabled             = 1 << 40
  #NSActivityIdleSystemSleepDisabled              = 1 << 20
  #NSActivitySuddenTerminationDisabled            = (1 << 14)
  #NSActivityAutomaticTerminationDisabled         = (1 << 15)
  #NSActivityUserInitiated                        = ($00FFFFFF | #NSActivityIdleSystemSleepDisabled)
  #NSActivityUserInitiatedAllowingIdleSystemSleep = (#NSActivityUserInitiated & ~#NSActivityIdleSystemSleepDisabled)
  #NSActivityBackground                           = $000000FF
  #NSActivityLatencyCritical                      = $FF00000000
 
  Procedure BeginWork(Option.q, Reason.s= "MyReason")
    Protected NSProcessInfo = CocoaMessage(0,0,"NSProcessInfo processInfo")
    If NSProcessInfo
      ProcedureReturn CocoaMessage(0, NSProcessInfo, "beginActivityWithOptions:@", @Option, "reason:$", @Reason)
    EndIf
  EndProcedure
 
  Procedure EndWork(Activity)
    Protected NSProcessInfo = CocoaMessage(0, 0, "NSProcessInfo processInfo")
    If NSProcessInfo
      CocoaMessage(0, NSProcessInfo, "endActivity:", Activity)
    EndIf
  EndProcedure
CompilerEndIf

; ----

Enumeration CustomEvent #PB_Event_FirstCustomValue
  #MyEvent_ServerMessage_Connect    ; Only TCP
  #MyEvent_ServerMessage_Data       ; UDP and TCP
  #MyEvent_ServerMessage_Disconnect ; Only TCP
  #MyEvent_ServerMessage_Error
EndEnumeration

Structure udtClient
  Connection.i
  Time.i
  Text.s
EndStructure

Structure udtServer
  *ThreadID
  *ServerID
  BindIP.s
  Port.i
  Error.i
  Exit.i
  Map Client.udtClient()
EndStructure

Threaded NewMap UdpConnection.i()

; ----

InitNetwork()

; ----

Procedure AllocateString(Text.s)
  Protected *mem.String
  *mem = AllocateStructure(String)
  *mem\s = Text
  ProcedureReturn *mem
EndProcedure

Procedure.s FreeString(*Text.String)
  Protected result.s
  If *Text
    result = *text\s
    FreeStructure(*Text)
  EndIf
  ProcedureReturn result
EndProcedure

; ----

Procedure thUdpServer(*ServerData.udtServer)
  Protected client, *buffer, cnt, *text, stx, etx, len, time
 
  CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
    Protected StopNap = BeginWork(#NSActivityLatencyCritical | #NSActivityUserInitiated, Hex(*ServerData))
  CompilerEndIf
   
  With *ServerData
    *Buffer = AllocateMemory(2048)
    Repeat
      Select NetworkServerEvent()
        Case #PB_NetworkEvent_Connect ; Only TCP
          PostEvent(#MyEvent_ServerMessage_Connect, 0, 0, 0, EventClient())
         
        Case #PB_NetworkEvent_Data ; TCP and UDP
          client = EventClient()
          If Not FindMapElement(\Client(), Str(client))
            AddMapElement(\Client(), Str(client))
            \Client()\Connection = client
          EndIf
          cnt = ReceiveNetworkData(client, *buffer, 2048)
          If cnt > 0
            \Client()\Text + PeekS(*buffer, cnt, #PB_UTF8 | #PB_ByteLength)
            \Client()\Time = ElapsedMilliseconds()
            stx = FindString(\Client()\Text, #STX$)
            If stx
              etx = FindString(\Client()\Text, #ETX$, stx)
              If etx
                stx + 1
                len = etx - stx
                *text = AllocateString(Mid(\Client()\Text, stx, len))
                \Client()\Text = Mid(\Client()\Text, etx + 1)
                PostEvent(#MyEvent_ServerMessage_Data, 0, client, 0, *text)
              EndIf
            EndIf
          ElseIf cnt < 0
            \Error = 3
            PostEvent(#MyEvent_ServerMessage_Error, 0, 0, 0, 3)
          EndIf
         
        Case #PB_NetworkEvent_Disconnect ; Only TCP
          PostEvent(#MyEvent_ServerMessage_Disconnect, 0, 0, 0, EventClient())
         
        Case #PB_NetworkEvent_None
          Delay(20)
          ; Clear resources
          time = ElapsedMilliseconds()
          ForEach \Client()
            If (time - \Client()\Time) >= 300000 ; 5 Minutes
              CloseNetworkConnection(\Client()\Connection)
              DeleteMapElement(\Client())
            EndIf
          Next
         
      EndSelect
     
    Until \Exit
   
    CloseNetworkServer(\ServerID)
    FreeMemory(*buffer)
   
    \ServerID = 0
    \Exit = 0
    ClearMap(\Client())
   
  EndWith
 
  CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
    EndWork(StopNap)
  CompilerEndIf
   
EndProcedure

; ----

Procedure InitUdpServer(*ServerData.udtServer, Port, BindIP.s = "")
 
  With *ServerData
    \BindIP = BindIP
    \Port = Port
    \Error = 0
    \Exit = 0
    \ServerID = CreateNetworkServer(#PB_Any, \Port, #PB_Network_UDP, \BindIP)
    If Not \ServerID
      \Error = 1
      ProcedureReturn 0
    EndIf
    \ThreadID = CreateThread(@thUdpServer(), *ServerData)
    If Not \ThreadID
      CloseNetworkServer(\ServerID)
      \ServerID = 0
      \Error = 2
      ProcedureReturn 0
    EndIf
    ProcedureReturn 1
  EndWith
EndProcedure

; ----

Procedure SendString(Port, Text.s)
  Protected r1, key.s
  If StringByteLength(Text, #PB_UTF8) > 2046
    ProcedureReturn 0
  EndIf
  key.s = "127.0.0.1:" + Port
  If Not FindMapElement(UdpConnection(), key)
    AddMapElement(UdpConnection(), key)
    UdpConnection() = OpenNetworkConnection("127.0.0.1", Port, #PB_Network_UDP)
  EndIf
  r1 = SendNetworkString(UdpConnection(), #STX$ + Text + #ETX$, #PB_UTF8)
  ProcedureReturn r1
EndProcedure

; ----

Procedure SendStringEx(IP.s, Port, Text.s)
  Protected r1, key.s
  If StringByteLength(Text, #PB_UTF8) > 2046
    ProcedureReturn 0
  EndIf
  key.s = IP + ":" + Port
  If Not FindMapElement(UdpConnection(), key)
    AddMapElement(UdpConnection(), key)
    UdpConnection() = OpenNetworkConnection(IP, Port, #PB_Network_UDP)
  EndIf
  r1 = SendNetworkString(UdpConnection(), #STX$ + Text + #ETX$, #PB_UTF8)
  ProcedureReturn r1
EndProcedure

; ----

Procedure ClearConnection()
  ForEach UdpConnection()
    CloseNetworkConnection(UdpConnection())
  Next
  ClearMap(UdpConnection())
EndProcedure

; ********


Example v1.02
Start twice programs with different local ports...
Code:
;-Example Window

IncludeFile "UdpServer.pb"

; Constant
Enumeration ;Window
  #Main
EndEnumeration

Enumeration ; Menu
  #Menu
EndEnumeration

Enumeration ; MenuItems
  #MenuSendText
  #MenuSendTextList
  #MenuExitApplication
EndEnumeration

Enumeration ; Gadgets
  #List
EndEnumeration

Enumeration ; Statusbar
  #Status
EndEnumeration

; Global Variable
Global ExitApplication

Global Server.udtServer

Global LocalPort = 2001
Global RemotePort = 2002

; Functions
Procedure UpdateWindow()
 
  Protected x, y, dx, dy, menu, status
 
  menu = MenuHeight()
  If IsStatusBar(#Status)
    status = StatusBarHeight(#Status)
  Else
    status = 0
  EndIf
  x = 0
  y = 0
  dx = WindowWidth(#Main)
  dy = WindowHeight(#Main) - menu - status
  ResizeGadget(#List, x, y, dx, dy)
 
EndProcedure

Procedure AddInfo(Text.s)
  Protected cnt
  AddGadgetItem(#List, -1, Text)
  cnt = CountGadgetItems(#List)
  If cnt > 1000
    RemoveGadgetItem(#List, 0)
    cnt - 1
  EndIf
  SetGadgetState(#List, cnt - 1)
  SetGadgetState(#List, -1)
EndProcedure

; Main
Procedure Main()
 
  Protected event, style, dx, dy, text.s, i
 
  style = #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget
  dx = 800
  dy = 600
 
  If OpenWindow(#Main, #PB_Ignore, #PB_Ignore, dx, dy, "Main", style)
   
    ; Menu
    CreateMenu(#Menu, WindowID(#Main))
    MenuTitle("Ablage")
    MenuItem(#MenuSendText, "Send &Text")
    MenuItem(#MenuSendTextList, "Send Text&list")
    MenuBar()
    MenuItem(#MenuExitApplication, "Be&enden")
    ; Gadgets
    ListViewGadget(#List, 0, 0, dx, dy)
   
    ; Statusbar
    CreateStatusBar(#Status, WindowID(#Main))
    AddStatusBarField(#PB_Ignore)
   
    UpdateWindow()
   
    BindEvent(#PB_Event_SizeWindow, @UpdateWindow(), #Main)
   
    ; Init Server
    If Not InitUdpServer(@Server, LocalPort)
      Debug "Error Init Server"
      End
    EndIf
   
    ; Init Window Timer
    AddWindowTimer(#Main, 1, 5000)
   
    ; Main Loop
    Repeat
      event = WaitWindowEvent()
      Select event
        Case #PB_Event_Menu
          Select EventMenu()
              CompilerIf #PB_Compiler_OS = #PB_OS_MacOS   
              Case #PB_Menu_About
               
              Case #PB_Menu_Preferences
               
              Case #PB_Menu_Quit
                ExitApplication = #True
               
              CompilerEndIf
             
            Case #MenuExitApplication
              ExitApplication = #True
             
            Case #MenuSendText
              text = InputRequester("", "", "")
              If text
                SendString(RemotePort, Text)
              EndIf
             
            Case #MenuSendTextList
              For i = 1 To 200
                SendString(RemotePort, "SendText Number " + Str(i))
              Next
          EndSelect
         
        Case #PB_Event_Gadget
          Select EventGadget()
            Case #List
              If EventType() = #PB_EventType_LeftDoubleClick
                text = InputRequester("", "", "")
                If text
                  SendString(RemotePort, Text)
                EndIf
              EndIf
             
          EndSelect
         
        Case #PB_Event_Timer
          SendString(RemotePort, "LifeTrigger")
         
        Case #PB_Event_CloseWindow
          Select EventWindow()
            Case #Main
              ExitApplication = #True
             
          EndSelect
         
        Case #MyEvent_ServerMessage_Connect ; Only TCP
          AddInfo("Connect: " + EventData())
         
        Case #MyEvent_ServerMessage_Data ; UDP and TCP
          AddInfo("Data: " + FreeString(EventData()))
         
        Case #MyEvent_ServerMessage_Disconnect ; Only TCP
          AddInfo("Disconnect: " + EventData())
         
        Case #MyEvent_ServerMessage_Error
          AddInfo("Error: Code" + EventData())
         
      EndSelect
     
    Until ExitApplication
   
    If Server\ThreadID
      Server\Exit = #True
      If WaitThread(Server\ThreadID, 5000) = 0
        KillThread(Server\ThreadID)
      EndIf
    EndIf
   
  EndIf
 
EndProcedure : Main()

End

_________________
My Projects ThreadToGUI / OOP-BaseClass / OOP-BaseClassDispatch / EventDesigner V3
PB v3.30 / v5.70 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace


Last edited by mk-soft on Tue Dec 24, 2019 2:04 am, edited 5 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: UDP Local Network Short Text Sending (All OS)
PostPosted: Fri Dec 13, 2019 3:31 pm 
Offline
Addict
Addict
User avatar

Joined: Fri May 12, 2006 6:51 pm
Posts: 2225
Location: Germany
Update Example with send many strings... :wink:

_________________
My Projects ThreadToGUI / OOP-BaseClass / OOP-BaseClassDispatch / EventDesigner V3
PB v3.30 / v5.70 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace


Top
 Profile  
Reply with quote  
 Post subject: Re: UDP Local Network Short Text Sending (All OS)
PostPosted: Fri Dec 13, 2019 6:49 pm 
Offline
Addict
Addict
User avatar

Joined: Fri May 12, 2006 6:51 pm
Posts: 2225
Location: Germany
Update v1.02

Strings can now also be sent to other computers in the network. Use the function SendStringEx(...).
To simplify starting the server the function InitUdpServer(...) has been added.

:wink:

_________________
My Projects ThreadToGUI / OOP-BaseClass / OOP-BaseClassDispatch / EventDesigner V3
PB v3.30 / v5.70 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace


Top
 Profile  
Reply with quote  
 Post subject: Re: UDP Local Network Short Text Sending (All OS)
PostPosted: Sat Dec 14, 2019 9:57 am 
Offline
Addict
Addict
User avatar

Joined: Sun Nov 05, 2006 11:42 pm
Posts: 4628
Location: Lyon - France
Hello Mk-Soft :D

Very interesting subject for me, i have see several methods for communicate between exe, but never this :shock:

But i have test your nice code, the second application appears one second and disappears and have this in the debugger
Quote:
Error Init Server
I'm with W10 X64 / v5.70 LTS X86

_________________
ImageThe happiness is a road...
Not a destination


Top
 Profile  
Reply with quote  
 Post subject: Re: UDP Local Network Short Text Sending (All OS)
PostPosted: Sat Dec 14, 2019 12:32 pm 
Offline
Addict
Addict
User avatar

Joined: Fri May 12, 2006 6:51 pm
Posts: 2225
Location: Germany
You have not changed the ports for the second program, or the port is already occupied.

Prog1
Code:
Global LocalPort = 2001
Global RemotePort = 2002

Prog2
Code:
Global LocalPort = 2002
Global RemotePort = 2001

_________________
My Projects ThreadToGUI / OOP-BaseClass / OOP-BaseClassDispatch / EventDesigner V3
PB v3.30 / v5.70 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace


Top
 Profile  
Reply with quote  
 Post subject: Re: UDP Local Network Short Text Sending (All OS)
PostPosted: Sat Dec 14, 2019 2:28 pm 
Offline
Addict
Addict
User avatar

Joined: Fri May 12, 2006 6:51 pm
Posts: 2225
Location: Germany
Optimisation
If you do not want to use the Map UdpConnection, you can also use optimized SendNetWorkString.

PB-Help: With UDP, PB is created internally only one entry, so you can send with the network functions

1: Init Connection
Code:
sender = OpenNetworkConnection("127.0.0.1", RemotePort, #PB_Network_UDP)


2: Send String
Code:
SendNetworkString(sender, #STX$ + "LifeTrigger" + #ETX$, #PB_UTF8)

_________________
My Projects ThreadToGUI / OOP-BaseClass / OOP-BaseClassDispatch / EventDesigner V3
PB v3.30 / v5.70 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace


Top
 Profile  
Reply with quote  
 Post subject: Re: UDP Local Network Short Text Sending (All OS)
PostPosted: Sun Dec 15, 2019 9:00 pm 
Offline
Addict
Addict
User avatar

Joined: Sun Nov 05, 2006 11:42 pm
Posts: 4628
Location: Lyon - France
MkSoft wrote:
You have not changed the ports for the second program, or the port is already occupied.
You have right, what a donkey i am :oops:
That's works now perfectly, thanks a lot for this sharing 8)

_________________
ImageThe happiness is a road...
Not a destination


Top
 Profile  
Reply with quote  
 Post subject: Re: UDP Local Network Short Text Sending (All OS)
PostPosted: Mon Dec 23, 2019 12:49 pm 
Offline
Addict
Addict
User avatar

Joined: Fri May 12, 2006 6:51 pm
Posts: 2225
Location: Germany
Update v1.04
- Small optimizations

:wink:

_________________
My Projects ThreadToGUI / OOP-BaseClass / OOP-BaseClassDispatch / EventDesigner V3
PB v3.30 / v5.70 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace


Top
 Profile  
Reply with quote  
 Post subject: Re: UDP Local Network Short Text Sending (All OS)
PostPosted: Mon Dec 23, 2019 7:35 pm 
Offline
Addict
Addict
User avatar

Joined: Sun Nov 05, 2006 11:42 pm
Posts: 4628
Location: Lyon - France
Thanks...works always also well 8)

_________________
ImageThe happiness is a road...
Not a destination


Top
 Profile  
Reply with quote  
 Post subject: Re: UDP Local Network Short Text Sending (All OS)
PostPosted: Mon Dec 23, 2019 8:47 pm 
Offline
Addict
Addict

Joined: Sun Sep 07, 2008 12:45 pm
Posts: 4519
Location: Germany
You are missing a flag
Code:
\Client()\Text + PeekS(*buffer, cnt, #PB_UTF8)

Should be
Code:
\Client()\Text + PeekS(*buffer, cnt, #PB_UTF8|#PB_ByteLength)


Top
 Profile  
Reply with quote  
 Post subject: Re: UDP Local Network Short Text Sending (All OS)
PostPosted: Tue Dec 24, 2019 2:05 am 
Offline
Addict
Addict
User avatar

Joined: Fri May 12, 2006 6:51 pm
Posts: 2225
Location: Germany
Update v1.05
- Bugfix PeekS

Thanks Infratec

_________________
My Projects ThreadToGUI / OOP-BaseClass / OOP-BaseClassDispatch / EventDesigner V3
PB v3.30 / v5.70 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace


Top
 Profile  
Reply with quote  
 Post subject: Re: UDP Local Network Short Text Sending (All OS)
PostPosted: Fri Feb 14, 2020 4:44 pm 
Offline
Enthusiast
Enthusiast

Joined: Fri Jul 14, 2006 8:53 pm
Posts: 672
Location: Malta
This looks quite nice
Thank you

_________________
I may not help with your coding
Just ask about mental issues!

http://www.lulu.com/spotlight/kingwolf
http://www.sen3.net


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 12 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 9 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye