Announcement

Collapse
No announcement yet.

TCP Server multi-threading (New topic)

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

  • TCP Server multi-threading (New topic)

    John - Michael - since you got me on the topic I went ahead and tried this, I like the idea of it but I'm not getting my %FD_READ

    If I do a CASE ELSE where %FD_READ is at, I get 4 "Msgbox"'s (I use those for debugging)....the browser says "Waiting for reply.."....

    I do record a connection, I do get as far as the INITDIALOG in the modeless dialog box....but that's it..

    Code:
    This first bit of code is from my main modal dialogProc call back function:
    
            g_nServertcp = FreeFile
            Tcp Open Server Addr nServerIP Port g_Port As g_nServertcp TimeOut g_TimeOut
            If Err Then
                sTmp = "Couldn't create socket!"
                Control Set Text CbHndl,%IDLABEL1, sTmp
            Else
                'What's the next TCP Count
                Tcp Notify g_nServertcp, Accept To g_hDlg As %TCP_ACCEPT
                sTmp = "Listening on " & g_ServerIP & ":" & Format$(g_Port)
                Control Set Text CbHndl,%IDLABEL1, sTmp
            End If
            Function = %TRUE
    
        Case %TCP_ACCEPT
            Select Case Lo(Word, CbLParam)
                Case %FD_ACCEPT 'Create the new thread here
                    Incr tcpCount
                    Call CreateNewConnectionThread(tcpCount)
                    Control Set Text CbHndl,%IDCONNLABELTL, Format$(tcpCount,"")
                    Function = %TRUE
            End Select
                          
         Case %WM_DESTROY
             Tcp Close g_nServertcp
             KillTimer CbHndl, %IDT_TIMER1
             Shell_NotifyIcon %NIM_DELETE, ti
             DestroyIcon ti.hIcon     
    
    
    '============================================<tcpThreadProc>===============================================================
    Function CreateNewConnectionThread(ByVal tcpCount As Long) As Long
    Local hThread   As Long
    Local lResult As Long
    
    Thread Create ConnectionThreadProc(ByVal tcpCount) To hThread
    Thread Close hThread To lResult
    'WaitForSingleObject hThread,%INFINITE
    Function = hThread 'grab thread handle to close prematurely and properly if need be.
    End Function
    '==========================================================================================
    Function ConnectionThreadProc(ByVal tcpCount As Long) As Long
    Local tDlg As Long
    Local lResult As Long
    Dialog New 0, "",,, 1,1, %WS_POPUP Or %WS_DLGFRAME  To tDlg 'modeless
    Dialog Show Modeless tDlg Call ConnectProc To lResult
    End Function
    '==========================================================================================
    CallBack Function ConnectProc() As Long
    Local sBuffer   As String
    Local sPacket   As String
    Local Header    As String
    Static hTcp     As Dword
    Local lHost     As String
    Local lResult   As Long
    
    
    Select Case CbMsg
        Case %WM_INITDIALOG
            hTcp = %INVALID_SOCKET
            hTcp = FreeFile
            Tcp Accept g_nServertcp As hTcp
            Tcp Notify hTcp, Recv Close To CbHndl As %TCP_ECHO
            Function = %TRUE
    
        Case %TCP_ECHO
            Select Case Lo(Word, CbLParam)
                Case %FD_READ
                    If hTcp <> %INVALID_SOCKET Then
                        'Grab client IP and insert here
                        lHost = RemoteIp(ByVal hTcp)
                        AppendTextToWindow g_txtHandle, TimeStamp() & " Connection established from: " & lHost
                        ' Perform a receive-loop until there is no data left (ie, the end of stream)
    '                sBuffer = ""
    '                sPacket = ""
                        Do
                          Tcp Recv hTcp, 1024, sBuffer
                          sPacket = sPacket + sBuffer
                          If Len(sPacket) > 4096 Then Exit Do 'Buffer overflow prevention
                        Loop Until sBuffer = "" Or IsTrue Eof(hTcp) Or IsTrue Err
                        sPacket = Left$(sPacket,Len(sPacket)-2) & String$(50,"-")
                        lResult = ParseAndUpdateLogfile(ByVal sPacket,ByVal hTcp) 'Updates window
                    ' <-------------Send data and disconnect------------->
                        If IsFalse lResult Then 'html
                            Header = "HTTP/1.1 200" & $CrLf
                            Header = Header & "Server: " & g_szMine & $CrLf
                            Header = Header & "Date: " & GetPCTimeandDate() & $CrLf
                            Header = Header & "Content-Type: text/html" & $CrLf
                            Header = Header & "Content-Length: " & Format$(Len(g_BBSDown)) & $CrLf
                            Tcp Send hTcp, Header & $CrLf
                            Tcp Send hTcp, g_BBSDown
                        Else 'jpg
                            Header = Header & "HTTP/1.1 200" & $CrLf
    '                        Header = Header & "Last-Modified: " & GetFileDateandTime(g_BBSDownImageFile) & " GMT" & $CrLf
                            Header = Header & "Server: " & g_szMine & $CrLf
                            Header = Header & "Date: " & GetPCTimeandDate() & $CrLf
                            Header = Header & "Content-Type: image/jpeg" & $CrLf
                            Header = Header & "Content-Length: " & Format$(Len(g_BBSDownImage)) & $CrLf
                            Header = Header & "Accept-range: bytes"  & $CrLf 'or something like that.
                            Header = Header & "Connection: close" & $CrLf
                            Tcp Send hTcp, Header & $CrLf
                            Tcp Send hTcp, g_BBSDownImage
                        End If
                        Tcp Close hTcp
                        hTcp = %INVALID_SOCKET
                        Dialog End CbHndl,%TRUE
                    ' <-------------Send data and disconnect------------->
                    'End connection here
                    End If
    
                Case %FD_CLOSE
                    Tcp Close hTcp
                    hTcp = %INVALID_SOCKET
            End Select
    End Select
    End Function
    '==========================================================================================
    Scott Turchin
    MCSE, MCP+I
    http://www.tngbbs.com
    ----------------------
    True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

  • #2
    Determined my thread is closing before anything can happen - Michael I know you've preached about doing this properly but I never understood Waitforsingleobject.

    IN this case per MS because I have a window with messages I have to use MsgWaitforMultipleOjbects.

    I don't understand how that works exactly.

    But I tried this, and it locked up my machine LOL Temporarily that is.

    help?

    Code:
    Function CreateNewConnectionThread(ByVal tcpCount As Long) As Long
    Local hThread   As Long
    Local lResult As Long
    
    Thread Create ConnectionThreadProc(ByVal tcpCount) To hThread
    Do Until lResult = %WAIT_TIMEOUT
        lResult = MsgWaitForMultipleObjects(1,hThread,%TRUE,5000,%QS_TIMER Or %QS_ALLINPUT)
    Loop
    Thread Close hThread To lResult
    Function = hThread 'grab thread handle to close prematurely and properly if need be.
    End Function
    Scott Turchin
    MCSE, MCP+I
    http://www.tngbbs.com
    ----------------------
    True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

    Comment


    • #3
      >Thread Close hThread To lResult
      >Function = hThread 'grab thread handle to close prematurely and properly if need

      THREAD CLOSE closes and invalidates the handle.

      If you need the handle in your calling procedure, don't close it!!
      Michael Mattias
      Tal Systems (retired)
      Port Washington WI USA
      [email protected]
      http://www.talsystems.com

      Comment


      • #4
        How do I get around that then, without using a global variable - that thread creates the modeless dialog box, so I want to wait.

        After doing more searching and reading it appears I "Should" be able to use the WaitForSingleObject API (??)..

        I could always do a sleep 10000 but that's not proper, the connection should never last more than 10 seconds unless someone is on 14.4k dialup....
        Scott Turchin
        MCSE, MCP+I
        http://www.tngbbs.com
        ----------------------
        True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

        Comment


        • #5
          >How do I get around that then, without using a global variable
          Code:
          Call CreateNewConnectionThread(tcpCount)  [b]TO hthread[/b]
          (hthread LOCAL or STATIC)
          ????

          Or, take a look at how I handled (no pun intended) open thread handles in this demo:
          GUI + Worker Thread + Abort Demo 11-24-07

          Basically, you return the thread handle (still open) to whatever procedure needs it. Thread handles do not automatically close when the thread function completes.

          If the handle is still open, you can use it in the WFSO and WFMO functions. (else you get the dreaded "INVALID_PARAMETER" error from Windows, which tells you not much at all).

          MCM
          PS: Another example of why I believe PB wishes they had used the syntax "THREAD CLOSE HANDLE" instead of just "THREAD CLOSE"
          Last edited by Michael Mattias; 11 Oct 2008, 09:17 AM.
          Michael Mattias
          Tal Systems (retired)
          Port Washington WI USA
          [email protected]
          http://www.talsystems.com

          Comment


          • #6
            It's local
            Local hThread As Long

            So I'm thinkign I'll have to do the polling method - I'll check your sample out..

            Still foggy on this one...not sure why...
            Scott Turchin
            MCSE, MCP+I
            http://www.tngbbs.com
            ----------------------
            True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

            Comment


            • #7
              So I'm thinkign I'll have to do the polling method ...Still foggy on this one...not sure why
              You never "have to" poll.

              If you are trying to set up a TCP function to "run until complete" and execute in its own thread of execution, I don't know what it is you want to know when that thread function completes; i.e., I can't tell from your code snippet what you are trying to do.

              It 'appears' you might be trying to maintain some kind of 'user count' (???).

              If so, you can use something like Win32: Memory Mapped Files/Control User Count April 26, 2001.

              That demo was created to work across processes, but no reason you can't do the same kind of thing across threads

              Or maybe you want to make sure all thread functions have completed before you allow the program to end? That's where you would use WFMO (with "all = true") against an array of thread handles.


              A paragraph of explanation would help; that should get you some ideas, anyway.

              MCM
              Michael Mattias
              Tal Systems (retired)
              Port Washington WI USA
              [email protected]
              http://www.talsystems.com

              Comment


              • #8
                No just trying to send an html file, and then close the connection.
                Right now I get success on the TCP Accept etc to TCP_ECHO but it never gets to the TCP_ECHO, which is now named TCP_HTML

                Code:
                '============================================<DialogProc>===============================================================
                CallBack Function DialogProc() As Long
                Static ti           As NOTIFYICONDATA 'For system tray
                Static p            As POINTAPI 'FOR pop up menu
                Static nServerIP    As Long
                Static tcpCount     As Long
                Static txtHandle    As Long
                Local lResult       As Long
                Local hResult       As Long
                Local lLoop         As Long
                Local sTmp          As String
                Dim hThread(1 To %MAXTHREADS) As Dword
                
                
                
                Select Case CbMsg
                    Case %WM_INITDIALOG
                        'Set timer to refresh the page EVERY 1 min
                        SetTimer CbHndl, %IDT_TIMER1,  60000, ByVal %NULL
                        Control Handle CbHndl,%IDLABEL1 To g_lblHandle
                        Control Handle CbHndl,%IDTEXT1 To g_txtHandle
                        Control Handle CbHndl, %IDSTATUSBAR To g_hStatus
                         ' Initialization handler
                         Graphic Attach CbHndl,%IDC_GC1,ReDraw
                         Graphic Color %Red,%Yellow
                         Graphic Clear
                         Graphic ReDraw
                         Call CylonEyeThread()
                
                        'Running in System Tray?
                        If IsTrue g_RuninSysTray Then
                             ' ** Add tray icon
                            ti.cbSize           = SizeOf(ti)
                            ti.hWnd             = CbHndl
                            ti.uID              = g_hInst
                            ti.uFlags           = %NIF_ICON Or %NIF_MESSAGE Or %NIF_TIP
                            ti.uCallbackMessage = %WM_TRAYICON
                            ti.hIcon            = g_hIcon
                            ti.szTip            = g_szMine & " " & g_szVer
                            Shell_NotifyIcon %NIM_ADD, ti
                            DestroyIcon ti.hIcon
                        End If
                
                        If IsTrue g_StayOnTop Then 'Stay on top or not
                            SetWindowPos CbHndl, %HWND_TOPMOST, 0, 0, 0, 0, %SWP_NOMOVE Or %SWP_NOSIZE
                        Else
                            SetWindowPos CbHndl, %HWND_NOTOPMOST, 0, 0, 0, 0, %SWP_NOMOVE Or %SWP_NOSIZE
                        End If
                
                        If IsFalse Len(g_ServerIP) Then 'Was not user specified, grab from socket
                            nServerIP = CCSServerIP(g_Port)
                        Else 'otherwise user specified the IP - if it fails they know it is their fault
                            nServerIP = inet_addr(ByVal VarPtr(g_ServerIP))
                        End If
                
                        'Write to log file:
                        UpdateLogfile "#Software: " & g_szMine & " " & g_szVer,%FALSE,%TRUE
                        UpdateLogFile "#Date: " & TimeStamp(),%FALSE,%TRUE
                        UpdateLogFile "#Fields: date time s-ip cs-method s-port c-ip cs(User-Agent) cs(Referer) sc-bytes cs-bytes",%FALSE,%TRUE
                
                        g_ntcpSocket = FreeFile
                        Tcp Open Server Addr nServerIP Port g_Port As g_ntcpSocket TimeOut g_TimeOut
                        If Err Then
                            sTmp = "Couldn't create socket!"
                            Control Set Text CbHndl,%IDLABEL1, sTmp
                        Else
                            'What's the next TCP Count
                            Tcp Notify g_ntcpSocket, Accept To g_hDlg As %TCP_ACCEPT
                            sTmp = "Listening on " & g_ServerIP & ":" & Format$(g_Port)
                            Control Set Text CbHndl,%IDLABEL1, sTmp
                        End If
                        Function = %TRUE
                
                    Case %TCP_ACCEPT
                        Select Case Lo(Word, CbLParam)
                            Case %FD_ACCEPT 'Create the new thread here
                                Incr tcpCount
                                hThread(tcpCount) = CreateNewConnectionThread(tcpCount)
                                Control Set Text CbHndl,%IDCONNLABELTL, Format$(tcpCount,"")
                                Control Set Focus CbHndl, %IDLABEL1
                                Function = %TRUE
                        End Select
                
                    Case %WM_TIMER
                        Select Case CbWParam
                          Case %IDT_TIMER1
                              g_BBSDown = LoadHtmlPage()
                              g_BBSDownImage = LoadImageFile()
                              sTmp = g_szMine & " " & g_szVer & " - " & g_szCopyrite
                              SendMessage g_hStatus, %WM_SETTEXT, 0, StrPtr(sTmp)
                              For lLoop = 1 To tcpCount
                                  Thread Status hThread(lLoop) To lResult
                                  Select Case lResult
                                      Case %THREADALIVE
                                          Iterate
                                      Case %FALSE
                                          'Function failed
                                          Thread Close hThread(lLoop) To hResult
                                          If IsFalse hResult Then Thread Close hThread(lLoop) To hResult  'TRY Again
                                  End Select
                              Next
                         End Select
                
                
                    Case %WM_SIZE
                        Control Send CbHndl,%IDSTATUSBAR,CbMsg,CbWParam,CbLParam
                    Case %WM_COMMAND
                      Select Case LoWrd(CbWParam)
                        Case %IDM_EXIT
                            If IsTrue g_UseSSL Then
                                sTmp = "Stopping sTunnel.."
                                SendMessage g_hStatus, %WM_SETTEXT, 0, StrPtr(sTmp)
                                sTmp = "stunnel"
                                sTmp = CCSStopService(ByVal CCSGetComputerName(), ByVal sTmp)
                            End If
                            g_Finished = %TRUE 'End Cylon eye AND tcp thread
                            Dialog End CbHndl,%TRUE
                         Case %IDM_HELP
                             sTmp = AppPath & "Help\Index.html"
                             ShellExecute ByVal %NULL, "open", ByVal StrPtr(sTmp), ByVal %NULL, ByVal %NULL, %SW_SHOWNORMAL
                             Function = %TRUE
                
                         Case %IDM_LOGFILE
                             sTmp = g_LogFile
                             ShellExecute ByVal %NULL, "open", ByVal StrPtr(sTmp), ByVal %NULL, ByVal %NULL, %SW_SHOWNORMAL
                             Function = %TRUE
                
                         Case %IDM_ABOUT
                             Call ccsShellAbout(CbHndl, _
                                                %FALSE, _
                                                g_szMine,_
                                                g_szVer,_
                                                g_szCCS,_
                                                g_szCopyrite,_
                                                "Computer Creations Software;http://www.tngbbs.com/ccs",_
                                                "",_
                                                g_hIcon)
                             Function = %TRUE
                         Case %IDM_OPTIONS
                             Call Options()
                             'This has to go here, locks up the & accelerators if done in OPTIONSDialogProc
                             If IsTrue g_StayOnTop Then 'Stay on top or not
                                 SetWindowPos g_hDlg, %HWND_TOPMOST, 0, 0, 0, 0, %SWP_NOMOVE Or %SWP_NOSIZE
                             Else
                                 SetWindowPos g_hDlg, %HWND_NOTOPMOST, 0, 0, 0, 0, %SWP_NOMOVE Or %SWP_NOSIZE
                             End If
                         Case %IDM_RESTORE
                             If IsWindowVisible(CbHndl) = %FALSE Then
                               Menu Attach g_hMenu, CbHndl
                               ShowWindow CbHndl, %SW_SHOW Or %SW_SHOWNORMAL
                               SetFocus CbHndl
                             End If
                
                
                     End Select
                
                
                     Case %WM_TRAYICON
                        Select Case LoWrd(CbLParam)
                        ' ** Left button press
                            Case %WM_LBUTTONDOWN, %WM_LBUTTONDBLCLK
                              If IsWindowVisible(CbHndl) = %FALSE Then
                                Menu Attach g_hMenu, CbHndl
                                ShowWindow CbHndl, %SW_SHOW Or %SW_SHOWNORMAL
                                SetFocus CbHndl
                              End If
                
                        ' ** Right button press
                            Case %WM_RBUTTONDOWN
                              If IsWindowVisible(CbHndl) = %FALSE Then
                                SetForegroundWindow CbHndl
                                GetCursorPos p
                                TrackPopupMenu g_pMenu, 0, p.x, p.y, 0, CbHndl, ByVal %NULL
                                Postmessage CbHndl, %WM_NULL, 0, 0
                              End If
                            Function = 1
                       End Select
                
                     Case %WM_DESTROY
                         Tcp Close g_ntcpSocket
                         KillTimer CbHndl, %IDT_TIMER1
                         Shell_NotifyIcon %NIM_DELETE, ti
                         DestroyIcon ti.hIcon
                
                
                
                     Case %WM_SYSCOMMAND
                         Select Case CbWParam
                             Case %SC_CLOSE
                                 Dialog End CbHndl,%TRUE
                                 Function = 1
                             Case %SC_MAXIMIZE
                                 Menu Attach g_hMenu, CbHndl
                             Case %SC_MINIMIZE
                                If IsFalse g_RunInSysTray Then Exit Function
                                ShowWindow CbHndl, %SW_HIDE
                                Menu Attach g_pMenu, CbHndl
                                Function = %TRUE
                                Exit Function
                         End Select 'cbwparam for syscommand
                
                    End Select
                
                End Function
                '============================================<tcpThreadProc>===============================================================
                Function CreateNewConnectionThread(ByVal tcpCount As Long) As Long
                Static hThread   As Long
                Local lResult As Long
                
                Thread Create ConnectionThreadProc(ByVal tcpCount) To hThread 'Unique number now
                Thread Close hThread To lResult
                Function = hThread 'grab thread handle to close prematurely and properly if need be.
                End Function
                '==========================================================================================
                Function ConnectionThreadProc(ByVal tcpCount As Long) As Long
                Local tDlg As Long
                Local lResult As Long
                Dialog New 0, "",,, 1,1, To tDlg 'modeless
                Dialog Show Modeless tDlg Call ConnectProc To lResult
                Function = lResult
                End Function
                '==========================================================================================
                CallBack Function ConnectProc() As Long
                Local sBuffer   As String
                Local sPacket   As String
                Local Header    As String
                Local lResult   As Long
                Static hTcp     As Dword
                Static lHost    As String
                Local ErrType   As Long
                
                Select Case CbMsg
                    Case %WM_INITDIALOG
                '        Dialog Show State cbhndl, %SW_HIDE 'hide the window from flashing up
                        SetTimer CbHndl, %IDT_TIMER2, 10000, ByVal %NULL
                '        hTcp = %INVALID_SOCKET
                        hTcp = FreeFile
                        Tcp Accept g_ntcpSocket As hTcp 'Debug shows #9 here
                        Tcp Notify hTcp, Recv Close To CbHndl As %TCP_HTML
                        ErrType = GetLastError()
                        If ErrType <> %ERROR_SUCCESS Then
                            Call AppendTextToWindow(ByVal sPacket)
                        End If
                        Function = %TRUE
                
                    Case %WM_TIMER 'IF They don't get connected in 5 seconds disconnect
                        Select Case CbWParam
                            Case %IDT_TIMER2
                                Tcp Close hTcp
                                hTcp = %INVALID_SOCKET
                                Dialog End CbHndl, %TRUE
                            End Select
                
                
                    Case %TCP_HTML
                        Select Case Lo(Word, CbLParam)
                            Case  %FD_READ
                                If hTcp <> %INVALID_SOCKET Then
                                    'Grab client IP and insert here
                                    lHost = RemoteIp(ByVal hTcp)
                                    AppendTextToWindow TimeStamp() & " Connection established from: " & lHost
                                    ' Perform a receive-loop until there is no data left (ie, the end of stream)
                                    sBuffer = ""
                                    sPacket = ""
                                    Do
                                      Tcp Recv hTcp, 1024, sBuffer
                                      sPacket = sPacket & sBuffer
                                      If Len(sPacket) > 4096 Then Exit Do 'Buffer overflow prevention
                                    Loop Until sBuffer = "" Or IsTrue Eof(hTcp) Or IsTrue Err
                                    sPacket = Left$(sPacket,Len(sPacket)-2) & String$(50,"-")
                                    lResult = ParseAndUpdateLogfile(ByVal sPacket,ByVal hTcp) 'Updates window
                                ' <-------------Send data and disconnect------------->
                                    If IsFalse lResult Then 'html
                                        Header = "HTTP/1.1 200" & $CrLf
                                        Header = Header & "Server: " & g_szMine & $CrLf
                                        Header = Header & "Date: " & GetPCTimeandDate() & $CrLf
                                        Header = Header & "Content-Type: text/html" & $CrLf
                                        Header = Header & "Content-Length: " & Format$(Len(g_BBSDown)) & $CrLf
                                        Header = Header & "Cache-Control: no-cache" & $CrLf
                                        Tcp Send hTcp, Header & $CrLf
                                        Tcp Send hTcp, g_BBSDown
                                    Else 'jpg
                                        Header = Header & "HTTP/1.1 200" & $CrLf
                '                        Header = Header & "Last-Modified: " & GetFileDateandTime(g_BBSDownImageFile) & " GMT" & $CrLf
                                        Header = Header & "Server: " & g_szMine & $CrLf
                                        Header = Header & "Date: " & GetPCTimeandDate() & $CrLf
                                        Header = Header & "Content-Type: image/jpeg" & $CrLf
                                        Header = Header & "Content-Length: " & Format$(Len(g_BBSDownImage)) & $CrLf
                                        Header = Header & "Accept-range: bytes"  & $CrLf 'or something like that.
                                        Header = Header & "Cache-Control: no-cache" & $CrLf
                                        Header = Header & "Connection: close" & $CrLf
                                        Tcp Send hTcp, Header & $CrLf
                                        Tcp Send hTcp, g_BBSDownImage
                                    End If
                                    Tcp Close hTcp
                                    hTcp = %INVALID_SOCKET
                                    Dialog End CbHndl,%TRUE
                                ' <-------------Send data and disconnect------------->
                                'End connection here
                                Else
                                    ErrType = GetLastError()
                                    If ErrType <> %ERROR_SUCCESS Then
                                        Call AppendTextToWindow(ByVal sPacket)
                                    End If
                                End If
                
                            Case %FD_CLOSE
                                Tcp Close hTcp
                                hTcp = %INVALID_SOCKET
                        End Select
                End Select
                End Function
                Last edited by Scott Turchin; 11 Oct 2008, 05:03 PM.
                Scott Turchin
                MCSE, MCP+I
                http://www.tngbbs.com
                ----------------------
                True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

                Comment


                • #9
                  >No just trying to send an html file, and then close the connection

                  Code:
                  TYPE  TheParams
                    szFile       AS ASCIIZ * %MAX_PATH 
                    connectionInfo 
                    hEventReady       AS LONG 
                    ThreadId            AS LONG 
                    ...
                  END TYPE 
                  
                  [THREAD ] FUNCTION   ConnectandSendFile ( BYVAL pParam AS TheParams PTR) AS LONG
                  
                    LOCAL P AS TheParams
                  
                     @Param.ThreadId = THREADID   ' set this for return 
                     P = @pParam       ' copy  params 
                      
                     SetEvent P.hHEventReady    ' release calling thread
                  
                     ' ---------------------------------
                    '  Connect, send file whatever here
                    ' ----------------------------------
                      hTCP = FREEFILE 
                      DIALOG new to hDLG or whatever 
                     
                  END FUNCTION
                  
                  MACRO   m_CreateThreadReadyEvent  =   CreateEvent (BYVAL %NULL, BYVAL %TRUE, BYVAL %FALSE, BYVAL %NULL)
                  ' params:1  lpsecuritydescriptor, NULL = default security
                  '        2  Manual Reset TRUE/FALSE
                  '        3  initial state FALSE=unsignalled
                  '        4  lpsz name, or %NULL for no name
                  
                  
                  FUNCTION WinMain () 
                  
                  LOCAL P AS TheParams 
                  
                       IF FileToSend THEN 
                           p.szFile = the file name 
                           p.ConnectionInfo = whatever 
                           p.heventready    = m_createThreadReadyEvent 
                           THREAD CREATE  ConnectAndSendFile (BYVAL VARPTR(P))  TO hThread 
                           WaitForSingleObject  P.hEventReady 
                           CloseHandle     P.hEventReady 
                           ThreadId =      P.ThreadId    ' return the thread ID of the launched thread 
                           ' ---------------------------------------------
                          ' at this point you have the threadid and hThread of launched thread 
                         '  save or not for other purposes
                           
                  
                     END IF
                  You use your parameter block to return the ID; your THREAD CREATE gives you an OPEN handle.

                  Because you do EVERYTHING in your THREAD FUNCTION, there is no data conflict (* as long as you lose your passion for GLOBAL variables)

                  You can create a seperate notification dialog in each Function but there's no reason they can't all use the same Dialog procedure... again assuming you terminate your relationship with GLOBAL variables.

                  Base everything in your DialogProc on stack-based variables (eg CBHNDL) and you'll be just fine.

                  MCM
                  Michael Mattias
                  Tal Systems (retired)
                  Port Washington WI USA
                  [email protected]
                  http://www.talsystems.com

                  Comment


                  • #10
                    Internet is not my strong suit but isn't...

                    "just trying to send an html file, and then close the connection."

                    the very definition of a "CGI" application?
                    Michael Mattias
                    Tal Systems (retired)
                    Port Washington WI USA
                    [email protected]
                    http://www.talsystems.com

                    Comment


                    • #11
                      No a CGI application resides ON a webserver whereas this *IS* a webserver, although I could build a CGI app inside of it (In essence it does have a built in web page, thus could be CGI)...

                      Common Gateway Interface, never understood that really, just a server app by definition..


                      Anyway so my thread is failing right here, I put a msgbox here and it never gets there....the thread closes, not sure why...

                      Ya I go with globals and then go back and clean them up and try to localize them, makes me think on how to do it...


                      Code:
                          Case %TCP_HTML
                      msgbox "DEBUG" - never happens.
                              Select Case Lo(Word, CbLParam)
                                  Case %FD_READ
                      Scott Turchin
                      MCSE, MCP+I
                      http://www.tngbbs.com
                      ----------------------
                      True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

                      Comment


                      • #12
                        Scott
                        Been away for a couple of days, but did say was not easy.
                        Have only had a very quick look at your first code. I dont believe PB allows you to have nested functions within PB functions, so your thread only contains the creation of a modeless dialog and then the function ends (as its not doing anything to keep it alive so your dialog is promptly destroyed and never gets notified of a recv and the thread ends. Think I said in a prior post that I couldn't see why you were using modeless dialogs.
                        If the dialog was Modal then the thread would stay alive until you did a DIALOG END in the callback after completing the TCP SEND. Of course all the threads are then using the same callback which has other complexities particularly speed and to which thread does the incoming data belong to.
                        Would be nice to have something like "Start of Thread" "End of Thread" statements so you could move a dialog and its callback to the same thread.
                        Can't see any help to the process by waiting for single objects, or MMF's.
                        Micheal
                        NO nothing to do with CGI. Properly done this is not simple and unfortunately mosts your posts are just confusing the problem.
                        John

                        Comment


                        • #13
                          >the thread closes, not sure why

                          "Threads" do not "close."

                          Thread HANDLES may be closed; but they don't do it on their own.

                          Thread FUNCTIONs end because you code them to end.
                          Michael Mattias
                          Tal Systems (retired)
                          Port Washington WI USA
                          [email protected]
                          http://www.talsystems.com

                          Comment


                          • #14
                            OK Michael I studied this and I am getting the drift, EXCELLENT way to eliminate a couple of global variables.

                            HOWEVER - The point of this new thread is to run in a modeless dialog box, in the event a TCP connection locks up (Ya know, the white screen of death) - it will do so in a thread and not the main program, thus the next connection gets af resh thread, new window etc..

                            For that reason I am having a hard time seeing how to pass the socket to a callback function for the modeless dialog box without using a global variable, but then that COULD be the problem.........


                            I'm still trying to incorporate your code ab ove though, this may be a while LOL, the pointer is giving PB 8.4 a bad time...
                            Scott Turchin
                            MCSE, MCP+I
                            http://www.tngbbs.com
                            ----------------------
                            True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

                            Comment


                            • #15
                              Scott
                              If you are using 8.03 or newer the look at THREADED variables they are Global to the thread (Yes PB put them in because sometimes GLOBALS are the best way to do things).
                              Agian I repeat my prior post, it will never work while you use Modeless Dialogs as you are now using them(there are ways).
                              There will never be a white screen of death as the thread dialogs should be hidden and if you do have a visible Dialog to give some info then it is only the main original in which you place info from the thread even Michael should agree with that.
                              John

                              Comment


                              • #16
                                Ok, just go to the next step...

                                Code:
                                FUNCTION PbMain() 
                                
                                     IF condition 
                                        THREAD CREATE  ConnectAndSendFIle  
                                
                                
                                FUNCTION ConnectAndSendFile 
                                
                                 LOCAL Params..
                                
                                   DIALOG NEW .... (Create window to receive TCP notifications) 
                                   DIALOG SET USER 1  = Pointer to parameter block 
                                   DIALOG SHOW somehow (modal is OK, since you won't block anything) 
                                
                                        
                                END FUNCTION
                                
                                FUNCTION DialogProc_TCPNotifications ..
                                LOCAL hThread AS LONG , PParam as Param TYPE PTR 
                                          WM_INITIDIALOG 
                                               DIALOG GET USER CBHNDL, 1 TO pParam
                                
                                               THREAD CREATE  TCPONLYFUNCTION (@Param)
                                That is, each "connect and send" uses two threads of execution.. one for it's Notification window and one for its "TCP Only" functions (which may hang) . The TCP notification window need not be visible.

                                It is actually not necessary to have a separate notification window for each separate thread: ONE window can handle ALL current "connect and send" sessions.... as long as you use nothing but stack-based variables. (There's that GLOBAL thing attempting to bite you in a tender place again).

                                I know I would do it with but one notification window:

                                Code:
                                FUNCTION PBMAIN() 
                                
                                       HWndNotify =  CreateWindowEx  (notification window, not visible, or maybe visible depending 
                                                           on my mood and the current phase of the moon) 
                                       DIALOG NEW   (primary user interface)  passing hWndNotify as a param

                                MCM
                                Last edited by Michael Mattias; 12 Oct 2008, 12:17 PM.
                                Michael Mattias
                                Tal Systems (retired)
                                Port Washington WI USA
                                [email protected]
                                http://www.talsystems.com

                                Comment


                                • #17
                                  Michael
                                  Why do you persist, you said it yourself
                                  Thread FUNCTIONs end because you code them to end.
                                  Scott descibed his problem his problem thus
                                  Determined my thread is closing before anything can happen
                                  What more is needed, read his code, he creates a MODELESS dialog and then ends the function, I would have thought that ended the thread in the way you described.
                                  Go read TCP on what it means when you create a new socket which happens on every ACCEPT.
                                  Forgetting all other complexities I have trouble understanding why his first simple and understandable problem is so hard for you to understand, just read his code, HE CREATES A WINDOW THEN THE THREAD ENDS.
                                  John

                                  Comment


                                  • #18
                                    No, he did NOT say the "thread ends"; he said, "the thread closes, not sure why"

                                    At which point I noted:
                                    "Threads" do not "close."
                                    Thread HANDLES may be closed; but they don't do it on their own.
                                    Thread FUNCTIONs end because you code them to end.
                                    For that matter, "THREADS" don't "END," either.

                                    Thread FUNCTIONs end.
                                    Thread OBJECTS are destroyed.
                                    Thread HANDLES may be closed.

                                    Go read TCP on what it means when you create a new socket which happens on every ACCEPT
                                    And you know this how? You have obtained the PowerBASIC proprietary information as to how its TCP XXXX functions are implemented?

                                    If I weren't just one hell of a nice guy, I'd suggest that your statement "his first simple and understandable problem is so hard for you to understand," constitutes a personal insult, which is not permitted here. But I can be be quite understanding when it's apparent English is not your first language.


                                    MCM
                                    Michael Mattias
                                    Tal Systems (retired)
                                    Port Washington WI USA
                                    [email protected]
                                    http://www.talsystems.com

                                    Comment


                                    • #19
                                      Michael
                                      Your knowledge of GUI far exceeds mine but in the following code snippet of Scotts
                                      Code:
                                      Function ConnectionThreadProc(ByVal tcpCount As Long) As Long
                                      Local tDlg As Long
                                      Local lResult As Long
                                      Dialog New 0, "",,, 1,1, %WS_POPUP Or %WS_DLGFRAME  To tDlg 'modeless
                                      Dialog Show Modeless tDlg Call ConnectProc To lResult
                                      End Function
                                      Where is the MESSAGE PUMP?
                                      I know I must be missing something but it seems to me that all this will do is create a dialog then immediately destroy it and as that is all that is in his thread isn't that End Function a coded Thread Function End?
                                      Is the Thread Object not destroyed at this point?
                                      John

                                      Comment


                                      • #20
                                        I'm not a DDT guy but I now what will happen if you do the SDK equivalent (CreateDialog).... the function will end. The window will still exist, so you could put a message loop in your code following the return from this function.

                                        With "tDlg" being LOCAL, there will be no way to talk to it on that return, but that is actually not necessary since in the "connectproc" you will have a handle via CBHNDL.
                                        Michael Mattias
                                        Tal Systems (retired)
                                        Port Washington WI USA
                                        [email protected]
                                        http://www.talsystems.com

                                        Comment

                                        Working...
                                        X