Announcement

Collapse
No announcement yet.

COM Interface: Planning Both Sides

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • John Petty
    replied
    Hi Dan
    Working with UDP is somewhat different as it is connectionless, which apart from meaning delivery is not guaranteed means you just can’t send a reply like the TCP server can. However it does give you the IP address of the sending computer so if you want to send information back then you just do a UDP Send. To illustrate here are some fragments from a private network DNS server I wrote a few years ago.
    Code:
    ‘ union for converting long IP to dotted IP
    UNION LtoB
        l AS LONG
        b(3) AS BYTE
    END UNION
    
    ‘ set up the window to receive messages
        DIALOG SHOW MODELESS hdlg, CALL GotUdt 'create a window to receive messages
        UDP OPEN PORT 13000 AS #1           'open a udp port to receive registrations
        UDP NOTIFY #1, RECV TO hdlg AS 888  'and have it notify when a message is received
    
    ‘ receive a message and reset for next
    CALLBACK FUNCTION GotUdt()
        SELECT CASE CBMSG
            CASE 888
                UDP RECV #1, FROM ip.l, pnumvar&, MyName$   'receive a registration
                'and extract the senders IP from the packet header and convert to dotted notation adding to registration string
                NewText$ = MyName$ + " " + FORMAT$(ip.b(0)) + "." + FORMAT$(ip.b(1)) + "." + FORMAT$(ip.b(2)) + "." + FORMAT$(ip.b(3))
                y& = INSTR(MyName$," on ")
                t$ = LEFT$(MyName$, y& - 1) 'extract the name from the string which also contains date etc
                l& = LEN(t$)
                FOR y& = 0 TO ccnt - 1
                    IF LEFT$(comps(y&),l&) = t$ THEN EXIT FOR   'check if name already registered
                    'note this test is case sensitive as it assumes you will never change the name
                    'being transmitted by the registration program
                NEXT
                IF y& < ccnt THEN
                    comps(y&) = newtext$    'yes so just replace current reg with new
                ELSE
                    comps(ccnt) = newtext$  'no so create a new registration
                    ccnt = ccnt + 1
                    REDIM PRESERVE comps(ccnt)
                END IF
                LISTBOX RESET hdlg, 1
                FOR y& = 0 TO ccnt - 1
                    LISTBOX ADD hdlg, 1, comps(y&)
                NEXT
                UDP CLOSE #1
                SLEEP 500
                UDP OPEN PORT 13000 AS #1
                UDP NOTIFY #1, RECV TO hdlg AS 888
    
    ‘*********** the sending program just sends it data at a regular period
        UDP OPEN AS #1
        EndlessLoop:
            Stext$ = compnme$ + " on " + DATE$ + " at " + TIME$ 
            “the sending IP number is by the name server
            'when it receives the packet
            UDP SEND #1, AT ip.l, 13000, stext$
    	'note ip.l is a long not dotted format
            'I use port 13000, you can choose any port number that is not already used on the
            'computer running the name server, of course you need to set your name server
            'to receive on that port
            SLEEP tme&
        GOTO EndlessLoop
        UDP CLOSE #1
    ‘ *******************

    Leave a comment:


  • Dan Gin zel
    replied
    Well, here's the latest.

    I discovered that one of the third-party programs that I'll be working with already uses 34000 for UDP communications! Therefore the direction is now set!

    Originally posted by John Petty View Post
    Here is a very simple TCP server DLL that allows control of and reporting on a VB6 program. The VB6 program just calls StartTCP passing a Callback address. The StartTCP Sub just starts a MODELESS (most important for a TCP server) hidden Dialog, the TCP and returns to VB6. When the VB6 prog is closing down it just calls CloseTCP which closes the Dialog and TCP server.
    External program (over Internet or LAN) simply connect to the TCP server and send a brief message. Depending on the message it either sends a control code back to the VB6 prog Callback or returns info to the caller.
    The port number you use is your own choice, preferably not a commonly used one.
    Well, that looks like as good of a starting point as any. I'll spend some time this weekend to digest it and reorganize it --that's how I learn how things work. I'll then rework it for UDP and use that as the basis for the final version. I do appreciate you taking the time to post the example as it will be most helpful!

    Thank you to everyone for your comments and assistance!

    Dan

    Leave a comment:


  • John Petty
    replied
    Dan
    Here is a very simple TCP server DLL that allows control of and reporting on a VB6 program. The VB6 program just calls StartTCP passing a Callback address. The StartTCP Sub just starts a MODELESS (most important for a TCP server) hidden Dialog, the TCP and returns to VB6. When the VB6 prog is closing down it just calls CloseTCP which closes the Dialog and TCP server.
    External program (over Internet or LAN) simply connect to the TCP server and send a brief message. Depending on the message it either sends a control code back to the VB6 prog Callback or returns info to the caller.
    The port number you use is your own choice, preferably not a commonly used one.
    Code:
    #PBFORMS CREATED V1.51
    #COMPILE DLL
    #DIM ALL
    
    #PBFORMS BEGIN INCLUDES
    #IF NOT %DEF(%WINAPI)
        #INCLUDE "WIN32API.INC"
    #ENDIF
    #PBFORMS END INCLUDES
    
    #PBFORMS BEGIN CONSTANTS
    %Bqt     = 1002
    %Dtcp    =  101
    %Tmess   = 1001
    #PBFORMS END CONSTANTS
    
    GLOBAL Htcp AS LONG
    GLOBAL LoggedIn AS LONG
    GLOBAL ManualLogout AS LONG
    GLOBAL LastAct AS STRING
    GLOBAL LastOrd AS STRING
    GLOBAL CurrentMonth AS STRING
    GLOBAL Cfg() AS STRING
    GLOBAL VBAdd AS DWORD
    GLOBAL WHndl AS DWORD
    
    DECLARE CALLBACK FUNCTION ShowDtcpProc()
    'DECLARE FUNCTION ShowDtcp(BYVAL hParent AS DWORD) AS LONG
    #PBFORMS DECLARATIONS
    DECLARE SUB GiveAction(BYVAL DoThis AS LONG)
    
    SUB StartTCP(BYVAL VBAddress AS DWORD) EXPORT
        LOCAL hDlg  AS DWORD
        LOCAL fi AS LONG
        LOCAL a AS LONG
        LOCAL s AS STRING
        LOCAL t AS STRING
        VBAdd = VBAddress
        fi = FREEFILE
        OPEN "c:\jiwamcaord.cfg" FOR INPUT AS fi
        WHILE EOF(fi) = 0
            LINE INPUT #fi, t
            a = INSTR(t, "=")
            IF a THEN
                s = UCASE$(TRIM$(LEFT$(t, a - 1)))
                t = TRIM$(RIGHT$(t, LEN(t) - a))
                SELECT CASE s
                    CASE "PERIOD START"
                        CurrentMonth = t
                END SELECT
            END IF
        WEND
        CLOSE fi
        DIALOG NEW %HWND_DESKTOP, "Hidden Dialog", 247, 162, 201, 121, TO hDlg
        CONTROL ADD TEXTBOX, hDlg, %Tmess, "", 5, 5, 190, 90, %WS_CHILD OR _
            %WS_VISIBLE OR %WS_VSCROLL OR %ES_LEFT OR %ES_MULTILINE OR _
            %ES_AUTOHSCROLL OR %ES_AUTOVSCROLL OR %ES_READONLY, _
            %WS_EX_CLIENTEDGE OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
            %WS_EX_RIGHTSCROLLBAR
        CONTROL ADD BUTTON,  hDlg, %Bqt, "Exit", 76, 100, 50, 15
    #PBFORMS END DIALOG
        TCP OPEN SERVER PORT 1122 AS #2    'create a TCP server to handle action requests
        TCP NOTIFY #2, ACCEPT TO hdlg AS 889    'and have it notify when a session is requested
        WHndl = hDlg
        DIALOG SHOW STATE hDlg, %sw_hide
        DIALOG SHOW MODELESS hDlg, CALL ShowDtcpProc
    END SUB
    
    SUB StopTCP() EXPORT
        TCP CLOSE #2
        DIALOG END WHndl
    END SUB
    
    SUB SaveState(Lact AS STRING, LIn AS LONG, MLOut AS LONG) EXPORT
        LoggedIn = Lin
        ManualLogout = MLOut
        LastAct = Lact
    END SUB
    
    SUB OrderDet(Lord AS STRING) EXPORT
        LastOrd = Lord
    END SUB
    
    
    CALLBACK FUNCTION ShowDtcpProc()
        LOCAL buffer AS STRING
        LOCAL s AS STRING
        LOCAL fi AS LONG
        LOCAL a AS LONG
    
        SELECT CASE AS LONG CBMSG
            CASE %WM_INITDIALOG
    
            CASE %WM_NCACTIVATE
                STATIC hWndSaveFocus AS DWORD
                IF ISFALSE CBWPARAM THEN
                    hWndSaveFocus = GetFocus()
                ELSEIF hWndSaveFocus THEN
                    SetFocus(hWndSaveFocus)
                    hWndSaveFocus = 0
                END IF
    
            CASE 889    'a new query session has been started
                htcp = FREEFILE
                TCP ACCEPT 2 AS htcp
                TCP NOTIFY htcp, RECV CLOSE TO CBHNDL AS 890
                SLEEP 500
    
            CASE 890    'the requesting packet has been received
                SELECT CASE CBLPARAM
                    CASE 1  '%FD_READ
                        TCP RECV htcp, 512, buffer    'the incoming packet will never be more than 512 bytes
                        buffer = TRIM$(buffer)
                        SELECT CASE buffer
                            CASE "Return Status"
                                s = LastAct + $CRLF
                                IF LoggedIn THEN
                                    s = s + "Logged in to Jiwa" + $CRLF
                                ELSE
                                    IF ManualLogout THEN
                                        s = s + " Manually "
                                    END IF
                                    s = s + "Logged out of Jiwa" + $CRLF
                                END IF
                                s = s + "Current period start date " + CurrentMonth + $CRLF
                                s = s + LastOrd
                                TCP SEND htcp, s 'send the reply back
                            CASE "Log Out"
                                CALL DWORD VBAdd USING GiveAction(2)
                                TCP SEND htcp, "Done" 'send the reply back
                            CASE "Send Log"
                                CALL DWORD VBAdd USING GiveAction(1)
                                TCP SEND htcp, "Done" 'send the reply back
                            CASE "Shutdown"
                                CALL DWORD VBAdd USING GiveAction(3)
                                TCP SEND htcp, "Done" 'send the reply back
                            CASE ELSE
                                IF INSTR(buffer, "Log In") THEN
                                    a = INSTR(buffer, "New Month")
                                    IF a THEN
                                        CurrentMonth = TRIM$(RIGHT$(buffer, LEN(buffer) - a - 9))
                                        REDIM cfg(0)
                                        fi = FREEFILE
                                        OPEN "c:\jiwamcaord.cfg" FOR INPUT AS fi
                                        WHILE EOF(fi) = 0
                                            LINE INPUT #fi, cfg(UBOUND(cfg))
                                            a = INSTR(cfg(UBOUND(cfg)) , "=")
                                            IF a THEN
                                                s = UCASE$(TRIM$(LEFT$(cfg(UBOUND(cfg)) , a - 1)))
                                                IF TRIM$(s) = "PERIOD START" THEN
                                                    cfg(UBOUND(cfg)) = "PERIOD START" + " = " + CurrentMonth
                                                END IF
                                            END IF
                                            REDIM PRESERVE cfg(UBOUND(cfg) + 1)
                                        WEND
                                        CLOSE fi
                                        fi = FREEFILE
                                        OPEN "c:\jiwamcaord.cfg" FOR OUTPUT AS fi
                                        FOR a = 0 TO UBOUND(cfg) - 1
                                            PRINT #fi, cfg(a)
                                        NEXT
                                        CLOSE fi
                                        CALL DWORD VBAdd USING GiveAction(5)
                                    ELSE
                                        CALL DWORD VBAdd USING GiveAction(4)
                                    END IF
                                    TCP SEND htcp, "Done" 'send the reply back
                                END IF
    
                        END SELECT
                        SLEEP 500
                    CASE &H20   'and close the session %FD_CLOSE
                        TCP CLOSE htcp
                END SELECT
            CASE %WM_COMMAND
                SELECT CASE AS LONG CBCTL
                    CASE %Tmess
    
                    CASE %Bqt
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                            TCP CLOSE #2
                            DIALOG END CBHNDL
                        END IF
    
                END SELECT
        END SELECT
    END FUNCTION

    Leave a comment:


  • Edwin Knoppert
    replied


    It is a tcp server using sqlite database..

    Leave a comment:


  • Dan Gin zel
    replied
    First, I want to thank everyone for the input. That's exactly what I needed to get the cognitive processes moving again.

    And now, for the winning entry:
    Originally posted by Knuth Konrad View Post
    That said, exchanging "strings" could easily be done via TCP communication. Look at the Echoserver (client/server) in you PB examples folder.
    The beauty of this solution is that I can use it between more than process, use it for multiple instance detection and here's the key: to use it between computers on a LAN. The latter opens up a whole new realm of possibilities that I had not before considered!

    I've been doing searches looking for existing code as I have little TCP/IP communications experience. Lots to learn by Friday (Demo Day.)

    (Now if someone has any tips or thoughts in this direction, I'm all ears!)

    Thanks again to all! Y'alls input is most appreciated!

    Dan

    Leave a comment:


  • Cliff Nichols
    replied
    An EXE and a DLL.
    Not to mention, the DLL can have its own "Windows/Dialog/etc"

    Leave a comment:


  • Bob Zale
    replied
    An EXE and a DLL.

    Leave a comment:


  • Edwin Knoppert
    replied
    Com servers behave much better than sendmessages and such.
    using sm you can lock up both apps.

    Leave a comment:


  • Michael Mattias
    replied
    There are many, many ways to exchange info between cooperating applications on the same computer...

    - Memory Mappped file objects
    - Window messages, eg WM_COPYDATA
    - Regular disk files
    - Pipes and Mailslots

    I'm sure I've forgotten some. Try a seach here on "interprocess communications."

    Leave a comment:


  • Knuth Konrad
    replied
    PB doesn't provide, as of yet, the ability to create COM servers. That's why you dont' find examples here. If you really like to go the COM way, I guess José Roca's forums would eb agood place to look at.

    That said, exchanging "strings" could easily be done via TCP communication. Look at the Echoserver (client/server) in you PB examples folder.

    Leave a comment:


  • Dan Gin zel
    started a topic COM Interface: Planning Both Sides

    COM Interface: Planning Both Sides

    Greetings! Tonight I'm inquring if anyone has any input regarding building a basic COM interface between two programs where I'm in control of both sides and where two-way communications (mostly simple strings) are required on each side, assuming COM is even the best mechanism.

    This is my first need for COM and have reviewed many of the examples on the board. All that I've discovered relate to controlling Excel, Word or some other application, and most of which I've been able to make work. However, I have not encountered any examples of a COM "server" in PowerBasic, supposing it can even be done.

    Are there any limitations or common mistakes made when building ones first COM interface? Any tip, suggestions and (hopefully) even a COM server code clip would be greatly appreciated.

    Also, I am very much open to alternate methods of inter-application communication where I can pass strings between them.

    Thanks,
    Dan
    Last edited by Dan Gin zel; 28 May 2008, 12:24 AM.
Working...
X