Announcement

Collapse
No announcement yet.

TCP Server multi-threading (New topic)

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

  • John Petty
    replied
    Scott
    In 8.04 Dialog Doevents has a problem, do a search.
    John

    Leave a comment:


  • Scott Turchin
    replied
    OK I did NOT have this in my Thread -

    DO
    DIALOG DOEVENTS
    LOOP

    So that solves that and it works, but it takes like 4 OR 5 seconds for the thread to fire up now, and for the image or html page to be displayed - hardly worth it in my opinion, especially if I get 50-100 concurrent connections (Not likely but hey...)

    FAR FAR faster just having all of that in my message pump for my callback function
    So forget the server thread - but I will take all the advice you've given on my Globals and get those into a TYPE.........


    So......Globals aside - I'm working on that, I'm not sure this is going to work....

    So I was under the assumption that DDT with MODELESS dialog boxes would also suspend like a Modal does...not so....

    This is entirely too slow...

    Code:
    '============================================<tcpThreadProc>===============================================================
    Function CreateNewConnectionThread(ByVal tcpCount As Long) As Long
    Static hThread   As Long
    Local lResult As Long
    Thread Create ConnectionThreadProc(ByVal tcpCount) To hThread
    WaitForSingleObject  hThread,10000
    Function = hThread 'grab thread handle to close prematurely and properly if need be.
    End Function
    '==========================================================================================
    Function ConnectionThreadProc(ByVal tcpCount As Long) As Long 'Creates a modeless dialog box in a new thread so to avoid locking up main app.
    Local tDlg As Long
    Local lResult As Long
    Dialog New 0, "",,, 1,1, To tDlg 'modeless
    Dialog Show Modeless tDlg Call ConnectProc To lResult
    Do While IsFalse lResult
      Dialog DoEvents
    Loop
    Function = lResult
    End Function
    '==========================================================================================
    CallBack Function ConnectProc() As Long
    Last edited by Scott Turchin; 13 Oct 2008, 07:15 PM.

    Leave a comment:


  • John Petty
    replied
    Originally posted by Michael Mattias View Post
    >
    (You do have this in your program somewhere? If not, that explains why you never get to where you want to go).

    MCM
    I thought you read his code, so what was this all about
    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.
    My first language is English, my second American. Do I now get an apology from the great guru?
    John

    Leave a comment:


  • John Petty
    replied
    Scott
    You posted while I was writing the last reply (am a slow typist, won't comment on my thinking speed with my age).
    First step, just change your thread dialog to MODAL, PB will now provide the message pump and this statement
    Dialog End CbHndl,%TRUE
    which you already have in the correct place will close the dialog and end the correct thread as each thread will have a different CBHNDL.
    You may have other issues with different options per user but this should be a good first step.
    John

    Leave a comment:


  • Michael Mattias
    replied
    >This is the modeless dialog message pump..

    Typo or stray comment?

    Message loop =
    Code:
    DO 
      DIALOG DOEVENTS
    LOOP
    
    or 
    WHILE GetMessage( 
        IF ISFALSE IsDlgMessage (
             TranslateMessage
             DispatchMessage
    (You do have this in your program somewhere? If not, that explains why you never get to where you want to go).

    MCM

    Leave a comment:


  • John Petty
    replied
    Michael
    I'm not a DDT guy
    Sorry I didn’t realise that, I thought everything GUI was you strength, specially seeing you have been making such positive assertions on the subject, whereas PB DDT has handled my simple needs.
    As such I have to rely on the Power Basic Manual which says
    A modeless dialog must always have a message pump running while the dialog is running. Without a message pump, a modeless dialog will not be able to receive messages to redraw itself, etc.
    Which just might explain why his callback function is never receiving the RECV message.
    …. the function will end. The window will still exist,
    Honestly I don’t know how PB DDT handles that in all cases but assume without any proof that seeing the thread will end with the End Function statement as shown in my prior post that PB as part of cleaning up after the thread closes will include closing the Dialog.
    Immediately after calling the thread create function Scott does a Thread Close so the handle will be invalidated, the thread will have ended etc. so though his statement
    Determined my thread is closing before anything can happen
    Might not by your standards be semantically correct I guess it actually is.
    Your latest “next step” example fascinates me but leaves me a little confused
    ONE window can handle ALL current "connect and send" sessions
    TCP NOTIFY RECV only allows you to give one message number so how does the re-entrant callback which now has a single CBHNDL and a single message number know which of the multiple current connections it is dealing with using either Globals or the Stack.
    John

    Leave a comment:


  • Scott Turchin
    replied
    Thanks John - so back to my original using globals such as the socket - it's still failing on the TCP NOTIFY.


    Code:
    This is the modeless dialog message pump..
    
    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, Accept Connect Recv Close  To CbHndl As %TCP_HTML
    '        Tcp Notify #hTcp, Recv Close To CbHndl As %TCP_HTML      
    
    
    
    'xxxxxxxxxxxxxxxxxx
    
    Never gets to this point:
    
    xxxxxxxxxxxxxxxxxxxxx
    
    
        Case %TCP_HTML
            Select Case Lo(Word, CbLParam)
                Case %FD_READ
                    If hTcp <> %INVALID_SOCKET Then

    Leave a comment:


  • Michael Mattias
    replied
    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.

    Leave a comment:


  • John Petty
    replied
    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

    Leave a comment:


  • Michael Mattias
    replied
    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

    Leave a comment:


  • John Petty
    replied
    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

    Leave a comment:


  • Michael Mattias
    replied
    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.

    Leave a comment:


  • John Petty
    replied
    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

    Leave a comment:


  • Scott Turchin
    replied
    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...

    Leave a comment:


  • Michael Mattias
    replied
    >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.

    Leave a comment:


  • John Petty
    replied
    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

    Leave a comment:


  • Scott Turchin
    replied
    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

    Leave a comment:


  • Michael Mattias
    replied
    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?

    Leave a comment:


  • Michael Mattias
    replied
    >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

    Leave a comment:


  • Scott Turchin
    replied
    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.

    Leave a comment:

Working...
X