Announcement

Collapse
No announcement yet.

TCP NOTIFY returns a file handle BUT TCP READ wants a file number...

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

  • TCP NOTIFY returns a file handle BUT TCP READ wants a file number...

    TCP NOTIFY returns a file handle BUT TCP READ wants a file number...
    Anyone have a neat way to either call TCP READ with a file handle OR convert a file handle to a file number?

    Same issue with TCP ACCEPT.

    I have a couple of ways I have been dealing with this but wanted to be sure there was not an easy way to convert back and forth.



  • #2
    Look in help file under TCP and UDP Communications
    An ECHO client and server using TCP
    https://duckduckgo.com instead of google

    Comment


    • #3
      Hi Mike
      That doesn't show what I am asking, that is for a single connection where you assume the connection file number = hEcho.

      What I am saying is if you have lots of connections then the CB.LPARAM (file handle) is what you are given when a %FD_READ or %FD_CLOSE is fired in the callback.

      So, to use TCP READ etc you need to convert the FILE_HANDLE to a FILE_NUMBER.

      Was wondering if there was a better way to do it...


      This is what I have been doing for years:

      Code:
       FUNCTION CONVERT_FILE_HANDLE_TO_FILE_NUMBER(FILE_HANDLE AS DWORD) AS LONG
      
        'FILE_HANDLE IS PASSED IN FROM CALLBACK CB.WPARAM
        'FILE_HANDLE_TO_NUMBER(CB.WPARAM)
      
      
         LOCAL Looper     AS LONG
         LOCAL hFileOsTry AS LONG
         LOCAL FileNumTry AS LONG
      
         Looper = 1                                'FILEATTR(Looper, 3) is one based
         DO
         FileNumTry = FILEATTR(Looper, 3)          '3 enumerates existing file numbers.
         IF FileNumTry = -1 THEN                   'No more handles to scan
           EXIT LOOP                               'FUNCTION will return zero, so nothing found, could also be setted to -1 if needed
         ELSE
           IF FILEATTR(FileNumTry, 0) THEN         '0 for "open state", return TRUE if file is open
             hFileOsTry = FILEATTR(FileNumTry, 2)  'Get the coresponding operating system file handle
             IF hFileOsTry = FILE_HANDLE THEN
               FUNCTION = FileNumTry
             END IF
           END IF
         END IF
         INCR Looper
         LOOP
      
      
      END FUNCTION

      Comment


      • #4
        Was wondering if there was a better way to do it...
        Socket tools

        Comment


        • #5
          Was wondering if there was a better way to do it...
          This is how SQLitening does it with a thread for each connection
          This is some modified code pulled out of the service SQLiteningServer.bas
          I left out the fixed header with the request.
          It is different, but might give you some ideas.
          Code:
          %WM_USER = &H400
          %Tcp_Notify = %WM_USER + 4093
          %FD_ACCEPT = 8
          
          TYPE Listeners_TYPE
             TcpFileNumber AS LONG        'The PB filenumber associated with socket
             hSocket AS DWORD             'The operating system file handle.
          END TYPE
          GLOBAL gListener AS Listeners_TYPE
          GLOBAL ghDlg AS DWORD
          
          FUNCTION PBMAIN () AS LONG
            DIALOG SHOW MODAL ghDlg CALL Dispatcher
          END FUNCTION
          
          CALLBACK FUNCTION Dispatcher
           SELECT CASE CBMSG
            CASE %Tcp_Notify
             IF LO(WORD, CBLPARAM) = %FD_ACCEPT THEN
              AcceptConnection CBWPARAM ' cbwParam contains the handle of the socket (FileAttr(hSock, 2) from accept event)
             END IF
           END SELECT
          END FUNCTION
          
          SUB AcceptConnection(BYVAL rhSocket AS DWORD)
           LOCAL TcpFileNumber AS LONG
           LOCAL h             AS LONG
           LOCAL q             AS QUAD
           TcpFileNumber = FREEFILE
           TCP ACCEPT gListener.TcpFileNumber AS TcpFileNumber
           q = MAK(QUAD, TcpFileNumber, gListener.hSocket)
           THREAD CREATE ConnectionMain(VARPTR(q)) TO h
           THREAD CLOSE h TO h
          END SUB
          
          THREAD FUNCTION ConnectionMain(BYVAL rqpAddr AS QUAD PTR ) AS LONG
           LOCAL tcpFileNumber AS LONG
           LOCAL hSocket       AS LONG
           LOCAL sBuffer       AS STRING
           tcpFileNumber = LO(DWORD, @rqpAddr)
           hSocket       = HI(DWORD, @rqpAddr)
           DO
              DO
                TCP RECV TcpFileNumber, 1024 * 32, sBuffer
                IF ISTRUE LEN(sBuffer) OR ISTRUE EOF(TcpFileNumber) THEN EXIT DO
             LOOP
             'process data
             EXIT  'if all done
           LOOP
           TCP CLOSE TcpFileNumber
          END FUNCTION
          https://duckduckgo.com instead of google

          Comment


          • #6
            Older code might be of value:
            https://forum.powerbasic.com/forum/u...s-with-threads
            https://duckduckgo.com instead of google

            Comment


            • #7
              Thanks Mike! Love to look at code ideas!!

              Comment


              • #8
                When TCP NOTIFY is executed it tells you (your program) what the handle is with the nFile you just used.

                You only need store the association before going on to other things, and losing the association. (no need to convert if you already know!)

                I suggest a 2D array. It may be GLOBAL or STATIC within the callback function.

                Code:
                global Files_and_Handles() as dword
                …
                dim Files_and_Handles(1, Cnt - 1) ' first is 0 for Handle returned, or 1 nFile
                                                  ' second for max count of associations to be stored. Or, REDIM PRESERVE as you do OPENs and NOTIFYs
                                                  '(do an ARRAY DELETE(item) when you do a TCP CLOSE so array doesn't grow with many OPENs and CLOSEs
                'after a NOTIFY command
                Files_and_Handles(0, CurAsc) = hSoc '(the return from NOTIFY)
                Files_and_Handles(1, CurAsc) = nFile '(that you used with that NOTIFY)
                Later when get a notify message search the "0"s in the array for handle. The "1" item at that index will be the nFile you need.

                Cheers,

                Dale

                Comment

                Working...
                X