Announcement

Collapse
No announcement yet.

Thread Synchronization - Is This Safe?

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

  • #21
    Hi Jerry

    Can you show me how you did "a single socket with overlapped I/O." I would like to give overlapped i/o a try. Thanks!

    Comment


    • #22
      Originally posted by David Clarke View Post
      Hi Jerry

      Can you show me how you did "a single socket with overlapped I/O." I would like to give overlapped i/o a try. Thanks!
      Sorry for the delay. I just spotted your post. I attached a couple of files that may help you out. The first is a console app that I was using to test multiple threads handling messages from a single socket (or course, it can also be a single socket). It uses overlapped I/O for the threads so may be useful. It is by no means a polished app, but it does work. Essentially, it looks for received UDP packets and responds by sending responses to the sender. The second app is a GUI for sending UDP messages to the first app. I'm not really a GUI person so it's also not elegant. I used PB Forms to assemble the interface.

      Enjoy!

      Attached Files

      Comment


      • #23
        I did enjoy, but 3-years late.

        Jerry's code is very fast so it didn't give dialog time to refresh.
        I changed default from sending 1 message to 1000 messages and receiving responses.
        Also refreshes control every 100-messages so you see something.

        SendTestMessage2.bas
        Code:
        #PBFORMS CREATED V2.01
        
        #COMPILE EXE
        #DIM ALL
        
        #PBFORMS BEGIN INCLUDES
        #RESOURCE "SendTestMessage.pbr"
        %USEMACROS = 1
        #INCLUDE ONCE "WIN32API.INC"
        #INCLUDE ONCE "COMMCTRL.INC"
        #INCLUDE ONCE "PBForms.INC"
        #PBFORMS END INCLUDES
        
        #PBFORMS BEGIN CONSTANTS
        %BTN_Send      = 1010
        %CHK_waitRecv  = 1015
        %FRM_Main      =  101
        %IDC_IPAddress = 1009
        %LBL_LABEL1    = 1004
        %LBL_LABEL2    = 1005
        %LBL_LABEL3    = 1006
        %LBL_LABEL4    = 1008
        %LBL_LABEL5    = 1012
        %LBL_LABEL6    = 1014
        %TXT_Count     = 1007
        %TXT_FarPort   = 1011
        %TXT_Message   = 1003
        %TXT_Port      = 1002
        %TXT_Status    = 1013
        #PBFORMS END CONSTANTS
        '--------------------------------------------------------------------------------------------------
        DECLARE CALLBACK FUNCTION ShowMainProc()
        DECLARE FUNCTION ShowMain(BYVAL hParent AS DWORD) AS LONG
        #PBFORMS DECLARATIONS
        
        '   ** Main Application Entry Point **
        '--------------------------------------------------------------------------------------------------
        FUNCTION PBMAIN()
          PBFormsInitComCtls (%ICC_WIN95_CLASSES OR %ICC_DATE_CLASSES OR %ICC_INTERNET_CLASSES)
          ShowMain %HWND_DESKTOP
        END FUNCTION
        '--------------------------------------------------------------------------------------------------
        GLOBAL ghDlg AS DWORD
        
        FUNCTION zIP2String ALIAS "zip2string" (BYVAL lAddr AS DWORD) EXPORT AS STRING
          LOCAL pAddr AS BYTE PTR
        
          pAddr=VARPTR(lAddr)
          FUNCTION = USING$("#_.#_.#_.#", @pAddr, @pAddr[1], @pAddr[2], @pAddr[3])
        END FUNCTION
        
        FUNCTION zString2IP ALIAS "zstring2ip" (BYREF sIPAddr AS STRING) EXPORT AS LONG
          REGISTER n      AS LONG
          LOCAL sWork     AS STRING         '
          LOCAL sTemp     AS STRING
        
          sIPAddr = REMOVE$(sIPAddr, ANY CHR$(0,32))    ' Make sure there's no spaces or nulls
          sWork = SPACE$(4)                             ' Build a buffer for calculations
          IF TALLY(sIPAddr,".") <> 3 THEN               ' Make sure we have exactly 3 periods
            EXIT FUNCTION
          ELSE
            FOR n = 1 TO 4                              ' Process four values for IPv4
              sTemp = PARSE$(sIPAddr, ".", n)           ' Pointer value adjusted by ParseString
        
              '---- Make sure data element is in range (num 0 to 255)
              IF LEN(sTemp) > 3 OR sTemp="" OR VERIFY(1, sTemp, "0123456789") OR VAL(sTemp) > 255 THEN
                EXIT FUNCTION                           ' Some problem with input string so get out
              ELSE
                ASC(sWork,n) = VAL(sTemp)               ' Looks OK.  Update output string.
              END IF
            NEXT n
          END IF
          FUNCTION = CVL(sWork)                         ' Move data to return value.
        
        END FUNCTION  ' zString2IP
        
        FUNCTION SendUdpMessage( _
            BYVAL locPort AS LONG, _
            BYVAL farAddr AS LONG, _
            BYVAL farport AS LONG, _
            BYVAL cnt     AS LONG, _
            BYREF sMsg    AS STRING _
            ) AS LONG
          REGISTER n AS LONG
          STATIC hSock  AS LONG
          LOCAL sBuff   AS STRING
          LOCAL rxPort  AS LONG
          LOCAL rxAddr  AS LONG
          LOCAL wait AS LONG
        
          CONTROL SET TEXT ghDlg, %txt_status, ""
          CONTROL DISABLE  ghDlg, %BTN_Send
          CONTROL SET TEXT ghDlg, %BTN_Send, "Wait"
        '  IF hSock = 0 THEN
            hSock = FREEFILE
            UDP OPEN PORT locPort AS hSock TIMEOUT 100
            IF ERR THEN
        '      MSGBOX "Error starting UDP socket
              BEEP
              CONTROL SET TEXT ghDlg, %txt_status, "Error starting UDP socket =" & STR$(ERR)
              EXIT FUNCTION
            END IF
        '  END IF
        
          FOR n = 1 TO cnt
            UDP SEND hSock, AT farAddr, farPort, sMsg
            IF ERR THEN
              'IF cnt = n THEN  'change from 1
                CONTROL SET TEXT ghDlg, %txt_status, "Error ssending message =" & STR$(ERR)
                MSGBOX "Error sending message =" & STR$(ERR)
                EXIT FUNCTION
              'END IF
            END IF
        
          CONTROL GET CHECK ghDlg, %CHK_waitRecv TO wait
          IF wait THEN
            UDP RECV hSock, FROM rxAddr, rxPort, sBuff
            IF ERR THEN
              IF cnt = 1 THEN
                CONTROL SET TEXT ghDlg, %txt_status, "Error receiving message =" & STR$(ERR)
                MSGBOX "Error receiving message =" & STR$(ERR)
              END IF
            ELSE
              'IF cnt = n THEN
                CONTROL SET TEXT ghDlg, %txt_status, "Resp" + STR$(n)+ "  from " & _
                $CRLF & zIp2String(rxAddr) & ":" & FORMAT$(rxPort)
                IF n MOD 100 = 0 THEN CONTROL REDRAW ghDlg,%txt_status:SLEEP 10
        
        '        MSGBOX "Received response message from " & zIp2String(rxAddr) & ":" & FORMAT$(rxPort)
              'END IF
            END IF
          END IF
          NEXT n
        
          CONTROL SET TEXT ghDlg, %BTN_Send, "Send"
          CONTROL ENABLE ghDlg, %BTN_Send
        
          '-- Wait for a bit and close the port. This gives the dest host a chance to send a response
          '   without getting a DestHostUnreachable error because we already shut down. 100ms should
          '   be long enough.
          SLEEP 100
          UDP CLOSE hSock
          DIALOG REDRAW ghDlg
        
        END FUNCTION
        
        '--------------------------------------------------------------------------------------------------
        '   ** CallBacks **
        '--------------------------------------------------------------------------------------------------
        CALLBACK FUNCTION ShowMainProc()
          LOCAL farPort AS DWORD
          LOCAL locPort AS DWORD
          LOCAL msgCnt  AS LONG
          LOCAL farAddr AS LONG
          LOCAL sMsg    AS STRING
        '  LOCAL hSock AS LONG
          LOCAL sTemp   AS STRING
        
        
          SELECT CASE AS LONG CB.MSG
            CASE %WM_INITDIALOG
              ' Initialization handler
        
            CASE %WM_NCACTIVATE
              STATIC hWndSaveFocus AS DWORD
              IF ISFALSE CB.WPARAM THEN
                ' Save control focus
                hWndSaveFocus = GetFocus()
              ELSEIF hWndSaveFocus THEN
                ' Restore control focus
                SetFocus(hWndSaveFocus)
                hWndSaveFocus = 0
              END IF
        
            CASE %WM_COMMAND
              ' Process control notifications
              SELECT CASE AS LONG CB.CTL
        
                  IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
        
                    '-- Test the local port value.
                    CONTROL SET TEXT CB.HNDL,%txt_status,"Sending ...":DIALOG REDRAW CB.HNDL
        
                    CONTROL GET TEXT CB.HNDL, %txt_port TO sTemp
        
                    locPort = VAL(sTemp)
                    IF (locPort = 0) OR (locPort > 65535) THEN
        '              MSGBOX "Local port value is out of range.", %MB_ICONWARNING OR %MB_TASKMODAL, "Port Validation"
                      BEEP
                      CONTROL SET TEXT ghDlg, %txt_status, "Invalid local port!"
                      EXIT FUNCTION
                    END IF
        
                    '-- Test the far port value.
                    CONTROL GET TEXT CB.HNDL, %txt_farport TO sTemp
                    farPort = VAL(sTemp)
                    IF (farPort = 0) OR (farPort > 65535) THEN
                      MSGBOX "Local port value is out of range.", %MB_ICONWARNING OR %MB_TASKMODAL, "Port Validation"
                      EXIT FUNCTION
                    END IF
        
                    '-- Test IP address.
                    CONTROL GET TEXT CB.HNDL, %idc_ipaddress TO sTemp
                    farAddr = zString2IP(sTemp)
        
                    '-- Get the message count.
                    CONTROL GET TEXT CB.HNDL, %txt_Count TO sTemp
                    msgCnt = VAL(sTemp)
        
                '    MSGBOX "%BTN_Send=" + FORMAT$(farAddr), %MB_TASKMODAL
                '    MSGBOX STR$(farPort), %MB_ICONWARNING, "Port Validation"
                CONTROL GET TEXT CB.HNDL, %txt_message TO sTemp
        
                SendUDPMessage locPort, farAddr, farPort, msgCnt, sTemp
        
                  END IF
        
              END SELECT
          END SELECT
        END FUNCTION
        
        '   ** Dialogs **
        '--------------------------------------------------------------------------------------------------
        FUNCTION ShowMain(BYVAL hParent AS DWORD) AS LONG
          LOCAL lRslt AS LONG
        
        #PBFORMS BEGIN DIALOG %FRM_Main->->
          LOCAL hDlg  AS DWORD
        
          DIALOG NEW hParent, "Send Message", 237, 168, 163, 162, %WS_POPUP OR _
            %WS_BORDER OR %WS_DLGFRAME OR %WS_SYSMENU OR %WS_MINIMIZEBOX OR _
            %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME OR %DS_CENTER OR _
            %DS_3DLOOK OR %DS_NOFAILCREATE OR %DS_SETFONT, %WS_EX_CONTROLPARENT OR _
            %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
          CONTROL ADD TEXTBOX,  hDlg, %TXT_Port, "9999", 40, 25, 30, 15, %WS_CHILD OR _
            %WS_VISIBLE OR %WS_TABSTOP OR %ES_LEFT OR %ES_AUTOHSCROLL OR %ES_NUMBER, _
            %WS_EX_CLIENTEDGE OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
            %WS_EX_RIGHTSCROLLBAR
          CONTROL ADD TEXTBOX,  hDlg, %TXT_Message, "My Message", 40, 45, 115, 25
          CONTROL ADD LABEL,    hDlg, %LBL_LABEL1, "Far Addr", 0, 5, 35, 15, _
            %WS_CHILD OR %WS_VISIBLE OR %SS_RIGHT OR %SS_CENTERIMAGE, %WS_EX_LEFT OR _
            %WS_EX_LTRREADING
          CONTROL ADD LABEL,    hDlg, %LBL_LABEL2, "Loc Port", 0, 25, 30, 15, _
            %WS_CHILD OR %WS_VISIBLE OR %SS_RIGHT OR %SS_CENTERIMAGE, %WS_EX_LEFT OR _
            %WS_EX_LTRREADING
          CONTROL ADD LABEL,    hDlg, %LBL_LABEL3, "Tx Msg", 5, 45, 30, 15, %WS_CHILD _
            OR %WS_VISIBLE OR %SS_RIGHT OR %SS_CENTERIMAGE, %WS_EX_LEFT OR _
            %WS_EX_LTRREADING
          CONTROL ADD TEXTBOX,  hDlg, %TXT_Count, "1000", 40, 115, 40, 15, %WS_CHILD OR _
            %WS_VISIBLE OR %WS_TABSTOP OR %ES_LEFT OR %ES_AUTOHSCROLL OR %ES_NUMBER, _
            %WS_EX_CLIENTEDGE OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
            %WS_EX_RIGHTSCROLLBAR
          CONTROL ADD LABEL,    hDlg, %LBL_LABEL4, "Msg Cnt", 5, 115, 30, 15, _
            %WS_CHILD OR %WS_VISIBLE OR %SS_RIGHT OR %SS_CENTERIMAGE, %WS_EX_LEFT OR _
            %WS_EX_LTRREADING
          CONTROL ADD "SysIPAddress32", hDlg, %IDC_IPAddress, "192.168.0.106", 40, 5, _
            100, 15, %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP, %WS_EX_CLIENTEDGE OR _
            %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
          CONTROL ADD BUTTON,   hDlg, %BTN_Send, "Send", 105, 135, 50, 20
          CONTROL ADD TEXTBOX,  hDlg, %TXT_FarPort, "9998", 125, 25, 30, 15, _
            %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %ES_LEFT OR %ES_AUTOHSCROLL _
            OR %ES_NUMBER, %WS_EX_CLIENTEDGE OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
            %WS_EX_RIGHTSCROLLBAR
          CONTROL ADD LABEL,    hDlg, %LBL_LABEL5, "Far Port", 85, 25, 35, 15, _
            %WS_CHILD OR %WS_VISIBLE OR %SS_RIGHT OR %SS_CENTERIMAGE, %WS_EX_LEFT OR _
            %WS_EX_LTRREADING
          CONTROL ADD TEXTBOX,  hDlg, %TXT_Status, "", 40, 75, 115, 30
          CONTROL ADD LABEL,    hDlg, %LBL_LABEL6, "Status", 5, 75, 30, 15, %WS_CHILD _
            OR %WS_VISIBLE OR %SS_RIGHT OR %SS_CENTERIMAGE, %WS_EX_LEFT OR _
            %WS_EX_LTRREADING
          CONTROL ADD CHECKBOX, hDlg, %CHK_waitRecv, "Wait For Recv", 95, 115, 60, 15
        #PBFORMS END DIALOG
          CONTROL SET CHECK hDlg, %CHK_waitRecv,1 'set checkbox to recv messages back
        
          '-- Local address is always the default host address.
          LOCAL farAddr AS LONG
          HOST ADDR TO farAddr
          CONTROL SET TEXT hDlg, %idc_ipaddress, zIp2String(farAddr) 'sTemp
        
          ghDlg = hDlg
        
          DIALOG SHOW MODAL hDlg, CALL ShowMainProc TO lRslt
        
        
        #PBFORMS BEGIN CLEANUP %FRM_Main
        #PBFORMS END CLEANUP
        
          FUNCTION = lRslt
        END FUNCTION
        Attached Files

        Comment

        Working...
        X