Announcement

Collapse
No announcement yet.

OVERLAPPED SOCKETS - The saga continues...

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

  • OVERLAPPED SOCKETS - The saga continues...

    The overlapped I/O model in Winsock offers applications better super performance without having to create a thread for each connection.
    In essence it is asynchronous socket communications with event signaling when there is data to be read or any of the other reasons a normal socket might block.
    These sockets do not block.

    All of my code uses TCP NOTIFY but I need to improve performance, actually the number of devices I can chat with on a single comm thread. I am told Overlapped I/O is the way to go forward.

    First I am trying to get one socket working. The code below has some of the parts working.

    Take a look and see if you can make some suggestions that might get this working. I will keep going on it too.

    The idea is to have a LISTENING socket that then hands off to the ACCEPTING socket.
    Then you do a WSAWaitForMultipleEvents until you are signaled then you do a WSARecv.

    I am still figuring this out so I may have some things out of order.

    When it is totally right it should be able to accept a thousand+ connections and then trigger an event when one of them wants to talk. All asynchronous.
    You can Telnet to the port to mess with it. I am going to write a device simulator to stress test it when I get it working. I only have 10 devices in my office but want to see how many It can handle.

    SO FAR:

    Code:
    #COMPILE EXE
    #DIM ALL
    
    #INCLUDE "Win32API.inc"
    
    
    GLOBAL GL_hDlg             AS DWORD
    GLOBAL GL_LOG_FILE_NUMBER  AS LONG
    
    
    ENUM CONTROLS SINGULAR
     ENUM_STARTING_NUMBER = 100
     TIMER_1
     LISTBOX_VIEWER
     TCP_EVENT
    END ENUM
    
    ENUM MESSAGES SINGULAR
     ENUM_STARTING_MESSAGESS_NUMBER = %WM_APP
     WM_SOCKET
    END ENUM
    
    '------------------------------------------------------------------------------
     FUNCTION PBMAIN () AS LONG
    
       MAIN_DIALOG
       MY_WSACleanup
    
     END FUNCTION
    '------------------------------------------------------------------------------
     FUNCTION MAIN_DIALOG() AS LONG
    
       LOCAL RESULT            AS LONG
       LOCAL DIALOG_HEIGHT     AS LONG
       LOCAL DIALOG_WIDTH      AS LONG
       LOCAL DIALOG_STYLE      AS LONG
       LOCAL DIALOG_STYLE_EX   AS LONG
       LOCAL LISTBOX_STYLE     AS LONG
       LOCAL LISTBOX_STYLE_EX  AS LONG
    
       DIALOG_HEIGHT = 320
       DIALOG_WIDTH  = 575
    
       DIALOG_STYLE    = %WS_POPUP OR %WS_CAPTION OR %WS_SYSMENU OR %WS_MINIMIZEBOX OR %WS_VISIBLE OR %DS_MODALFRAME OR %DS_CENTER OR %DS_3DLOOK OR %DS_NOFAILCREATE OR %DS_SETFONT
       DIALOG_STYLE_EX = %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
    
       LISTBOX_STYLE    = %WS_CHILD OR %WS_VISIBLE OR %WS_BORDER OR %WS_TABSTOP OR %WS_VSCROLL OR %LBS_NOTIFY OR %LBS_DISABLENOSCROLL
       LISTBOX_STYLE_EX = %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
    
       DIALOG NEW %HWND_DESKTOP, "WinSock2_Test", 0, 0, DIALOG_WIDTH, DIALOG_HEIGHT, DIALOG_STYLE, DIALOG_STYLE_EX, TO GL_hDlg
    
       CONTROL ADD LISTBOX, GL_hDlg, %LISTBOX_VIEWER,,  10, 10, 575-20, 320-60, LISTBOX_STYLE, LISTBOX_STYLE_EX
    
       DIALOG SHOW MODAL GL_hDlg, CALL MAIN_DIALOG_CALLBACK
    
     END FUNCTION
    '------------------------------------------------------------------------------
     CALLBACK FUNCTION MAIN_DIALOG_CALLBACK
    
        SELECT CASE AS LONG CB.MSG
    
          CASE %WM_INITDIALOG
            SETTIMER(GL_hDlg,  %TIMER_1,  200)
    
          CASE %WM_TIMER
            KILLTIMER(GL_hDlg, %TIMER_1)
            START_COMM_THREAD
    
        END SELECT
    
     END FUNCTION
    
    '------------------------------------------------------------------------------
     FUNCTION START_COMM_THREAD()AS LONG
    
        LOCAL THREAD_HANDLE     AS LONG
        LOCAL THREAD_RESULT     AS LONG
    
        THREAD CREATE THREADED_COMM_THREAD(0) TO THREAD_HANDLE
        THREAD CLOSE  THREAD_HANDLE TO THREAD_RESULT
    
     END FUNCTION
    '------------------------------------------------------------------------------
     THREAD FUNCTION THREADED_COMM_THREAD(BYVAL NO_VAL AS LONG)AS LONG
      ON ERROR GOTO ERROR_CONTROL
    
       LOCAL RESULT_LONG          AS LONG
    
        LOCAL LISTENING_SOCKET     AS DWORD
        LOCAL ACCEPTING_SOCKET     AS DWORD
        LOCAL TYPE_SOCKET_ADDRESS  AS sockaddr_in
    
        LOCAL nBytesReceived       AS LONG
        LOCAL nFlags               AS LONG
    
        LOCAL MY_WSAOVERLAPPED     AS WSAOVERLAPPED
        LOCAL MY_WSAPROTOCOL_INFOA AS WSAPROTOCOL_INFOA
    
        LOCAL MY_WSADATA           AS WSADATA
    
       'The WSAStartup function initiates use of the Winsock DLL by a process.
        RESULT_LONG = WSAStartup(MAKWRD(2, 2), MY_WSADATA)
    
       'The WSASocket function creates a socket that is bound to a specific transport-service provider.
        LISTENING_SOCKET = WSASocket(%AF_INET, %SOCK_STREAM, %IPPROTO_TCP, BYVAL 0, 0, %WSA_FLAG_OVERLAPPED)
    
       'Set up the sock addr structure that the listening socket will be bound to. In this case, the structure holds the local IP address and the port.
        TYPE_SOCKET_ADDRESS.sin_family = %AF_INET
        TYPE_SOCKET_ADDRESS.sin_port = htons(4070)
        TYPE_SOCKET_ADDRESS.sin_addr.s_addr = inet_addr("192.168.1.193") 'or htonl(%INADDR_ANY)
    
    
       'The bind function associates a local address with a socket. Bind the listening socket to the IP address and port.
        RESULT_LONG = bind(BYVAL LISTENING_SOCKET, BYVAL VARPTR(TYPE_SOCKET_ADDRESS),  SIZEOF(TYPE_SOCKET_ADDRESS))
    
       'The listen function places a socket in a state in which it is listening for an incoming connection.
        RESULT_LONG = listen(LISTENING_SOCKET, 5)
    
    
        TEXT_TO_SCREEN "IM WAITING FOR THE LISTENING SOCKET TO BE CONTACTED BY SOMEONE WANTING TO COMMUNICATE"
        ACCEPTING_SOCKET =  WSAAccept(LISTENING_SOCKET, BYVAL VARPTR(TYPE_SOCKET_ADDRESS), SIZEOF(TYPE_SOCKET_ADDRESS), 0, 0)
        TEXT_TO_SCREEN "ACCEPTING_SOCKET " + FORMAT$(WSAGetLastError) + " - "+ FORMAT$(ACCEPTING_SOCKET)
    
        LOCAL PTR_IP_ADDRESS AS BYTE POINTER
        PTR_IP_ADDRESS = VARPTR(TYPE_SOCKET_ADDRESS.sin_addr)
    
        TEXT_TO_SCREEN "CONNECTED IP = " + USING$("#_.#_.#_.#", @PTR_IP_ADDRESS, @PTR_IP_ADDRESS[1], @PTR_IP_ADDRESS[2], @PTR_IP_ADDRESS[3])
    
        MY_WSAOVERLAPPED.hEvent = WSACreateEvent
    
        LOCAL my_pointer AS ASCIIZ POINTER
        LOCAL my_asciiz  AS ASCIIZ *4096
    
        my_pointer = VARPTR(my_asciiz)
    
        wsBuf.dLen = 4096
        wsBuf.buf  = my_pointer
    
    
        RESULT_LONG = WSARecv(ACCEPTING_SOCKET, wsBuf, 1, nBytesReceived, nFlags, MY_WSAOVERLAPPED, 0)
        WSARecv_Error = WSAGetLastError
    
        IF WSARecv_Error = 997 THEN
          TEXT_TO_SCREEN "Error 997 - I think this is good as it means an Overlapped I/O operation is in progress.
         ELSE
          TEXT_TO_SCREEN "Last Error = " + FORMAT$(WSAGetLastError)
        END IF
    
        TEXT_TO_SCREEN FORMAT$(nBytesReceived) + " - " + my_asciiz
    
    
    
       EXIT FUNCTION
    
       ERROR_CONTROL:
       MSGBOX ERROR$  
       END FUNCTION
    '------------------------------------------------------------------------------
     FUNCTION CompletionROUTINE(dwError AS DWORD, cbTransferred AS DWORD, lpOverlapped AS WSAOVERLAPPED, dwFlags AS DWORD)AS LONG
    
       MSGBOX "CompletionROUTINE"
    
     END FUNCTION
    '------------------------------------------------------------------------------
     FUNCTION MY_WSACleanup()AS LONG
    
       WSACleanup
       IF WSACleanup = 0 THEN TEXT_TO_SCREEN "WSACleanup"
    
     END FUNCTION
    '------------------------------------------------------------------------------
     FUNCTION TEXT_TO_SCREEN (TEXT_STRING AS STRING) AS LONG
       LOCAL LISTBOX_COUNT AS LONG
    
       LISTBOX ADD GL_hDlg, %LISTBOX_VIEWER, " " + TEXT_STRING
       LISTBOX GET COUNT GL_hDlg, %LISTBOX_VIEWER TO LISTBOX_COUNT
       CONTROL SEND GL_hDlg, %LISTBOX_VIEWER, %LB_SETTOPINDEX, LISTBOX_COUNT-1, 0
     END FUNCTION
    '------------------------------------------------------------------------------




    Last edited by David Clarke; 11 Jan 2020, 09:48 PM.
Working...
X