Results 1 to 2 of 2

Thread: Vb6 - simple tcp connect

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Dec 2012
    Posts
    1,005

    Vb6 - simple tcp connect

    During the process of trying to figure out NAT Traversal (how to get around the problem of NAT blocking external connections), I had to simplify the process of TCP/IP connections. NewSocket was just too complex to start experimenting with it.

    PrjTest3.vbp is a very simple example of connecting to a listening socket, and may help some users to understand how the Socket API (ws2_32.dll) functions in Vista or better operating systems. It does not contain a lot of error handling, it does not work with UDP, it does not work with IPv6, and it does not receive messages.

    In the Form_Load event, the Winsock service is started (WSAStartup), and the destination IP Address & Port are defined. In cmdConnect_Click, an IPv4 TCP socket is created using a Socket call (aliased API_Socket). Then the local Socket Address structure (sa_local) is populated. This is where Version 2 of the Socket API differs substantially from Version 1. When using GetAddrInfo, binding to a particular socket is not required. We simply use address 0.0.0.0 and port 0, and GetAddrInfo will consult the local DNS to get the Server information and bind to the socket using the appropriate local interface and the first available local port. Because we are using an IP address instead of a domain name, that trip to the local DNS is not necessary. There will only be one address in the linked list, and we copy that information to the Hints structure. From there, we copy the socket portion to sa_dest. Now we have all the information necessary to send a Connection Request (SYN) to the destination. The destination should respond with a SYN-ACK, and the local socket should send an ACK (this is all handled by the API). Once connected, we send a simple text message.

    That is about as far as we can go without implementing a callback procedure to intercept messages from the operating system. NewSocket uses Emiliano Scavuzzo's subclassing technique, which does not cause the IDE to crash and is able to differentiate the individual system messages from each socket. To put a socket into the listening mode is similar, but a little more complex. We have to create a socket, bind it to a user defined listening port, and put the socket into the listening mode with API_Listen. When a ConnectionRequest is received from the other end, the socket is closed, the connection is accepted on a different socket, and the socket once again is placed in the listening mode. This allows the server to accept multiple connections on the same port number. There is one caveat here though. Servers normally use blocking calls (each connection is on a separate thread) to handle large numbers of connections. However, we are using non-blocking calls, and the error WSAEWOULDBLOCK is not uncommon and should be ignored.

    J.A. Coutts
    Attached Files Attached Files

  2. #2

    Thread Starter
    Fanatic Member
    Join Date
    Dec 2012
    Posts
    1,005

    Re: Vb6 - simple tcp connect

    Upon further testing, I found that populating the local Socket Address structure is totally unnecessary, and is a holdover from Version 1. If however you want to use a specific local port, you need to allow GetAddrInfo to select the first available port, and then bind to the desired port using the local Socket Address structure. Bind will fail if the port is currently being used or is in a TIME_WAIT condition

    J.A. Coutts
    Code:
    Private Declare Function API_Bind Lib "ws2_32.dll" Alias "bind" (ByVal s As Long, ByRef name As sockaddr, ByRef namelen As Long) As Long
    
    Private Sub cmdConnect_Click()
        Dim sa_local As sockaddr
        Dim sa_dest As sockaddr
        Dim lRet As Long
        Dim Hints As addrinfo
        Dim ptrResult As Long
        Dim bTmp() As Byte
        'Create IPv4 TCP socket
        hSocket = API_Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
        If hSocket > 0 Then
            Debug.Print "Socket # " & CStr(hSocket) & " created!"
        Else
            Debug.Print "Failed to create socket!"
            Exit Sub
        End If
        'Recover info about the destination.
        Hints.ai_family = AF_INET
        lRet = API_GetAddrInfo(sServer, sPort, VarPtr(Hints), ptrResult)
        Hints.ai_next = ptrResult   'Point to first structure in linked list
        'Normally, we would supply a name and getAddrInfo would use the DNS server
        'to collect all the available IP address information in the linked list.
        'But we have supplied the IP address, so there will only be one, and that
        'information is copied to the destination sock address.
        CopyMemory Hints, ByVal Hints.ai_next, LenB(Hints) 'Copy next address info to Hints
        CopyMemory sa_dest, ByVal Hints.ai_addr, LenB(sa_dest)    'Save sockaddr portion
        Call DebugPrintByte("sa_dest", sa_dest.sa_data)
        'Populate the local sockaddr
        sa_local.sa_family = AF_INET
        sa_local.sa_data(0) = &H6 'Set local port address to port 1536 (&H0600)
        sa_local.sa_data(1) = &H0
        If API_Bind(hSocket, sa_local, LenB(sa_local)) = -1 Then
            Debug.Print "Bind Failed!"
            Exit Sub
        Else
            Debug.Print "Bind to local port succeeded!"
        End If
        'Connect to sockaddr
        lblStatus.Caption = "Connecting!"
        If API_Connect(hSocket, sa_dest, LenB(sa_dest)) = -1 Then
            lblStatus.Caption = "Could not connect!"
        Else
            lblStatus.Caption = "Connected!"
        End If
        bTmp = StrToByte("Hello!" & vbCrLf)
        lRet = API_Send(hSocket, bTmp(0), UBound(bTmp) + 1, 0&)
    End Sub

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width