Winsock with VBA

Copper Contributor

Our Senior It manager left the company without and the code he developed we not too sure how to the following:

(1) Bind the connection between the client and the server

(2) Connect from the client to the server

(3) Send data and receipt

 

Below is the module, any idea to direct us to right path will be highly appreciated:

 

 

Option Compare Database
Option Explicit

' Constants ----------------------------------------------------------
Const INVALID_SOCKET = -1
Const WSADESCRIPTION_LEN = 256
Const SOCKET_ERROR = -1

' Typ definitions ----------------------------------------------------

Private Type wsaData
wVersion As Integer
wHighVersion As Integer
szDescription(0 To WSADESCRIPTION_LEN) As Byte
szSystemStatus(0 To WSADESCRIPTION_LEN) As Byte
iMaxSockets As Integer
iMaxUdpDg As Integer
lpVendorInfo As Long
End Type

Private Type ADDRINFO
    ai_flags As Long
    ai_family As Long
    ai_socktype As Long
    ai_protocol As Long
    ai_addrlen As Long
    ai_canonName As LongPtr 'strptr
    ai_addr As LongPtr 'p sockaddr
    ai_next As LongPtr 'p addrinfo
End Type


' Enums ---------------------------------------------------------------

Enum AF
AF_UNSPEC = 0
AF_INET = 2
AF_IPX = 6
AF_APPLETALK = 16
AF_NETBIOS = 17
AF_INET6 = 23
AF_IRDA = 26
AF_BTH = 32
End Enum

Enum sock_type
SOCK_STREAM = 1
SOCK_DGRAM = 2
SOCK_RAW = 3
SOCK_RDM = 4
SOCK_SEQPACKET = 5
End Enum

' External functions --------------------------------------------------

Public Declare PtrSafe Function WSAStartup Lib "Ws2_32.dll" (ByVal wVersionRequested As Integer, ByRef data As wsaData) As Long
Public Declare PtrSafe Function connect Lib "Ws2_32.dll" (ByVal socket As Long, ByVal sockaddr As Long, ByVal namelen As Long) As Long
Public Declare PtrSafe Sub WSACleanup Lib "Ws2_32.dll" ()
Private Declare PtrSafe Function GetAddrInfo Lib "Ws2_32.dll" Alias "getaddrinfo" (ByVal NodeName As String, ByVal ServName As String, ByVal lpHints As LongPtr, lpResult As LongPtr) As Long
Public Declare PtrSafe Function ws_socket Lib "Ws2_32.dll" Alias "socket" (ByVal AF As Long, ByVal stype As Long, ByVal Protocol As Long) As Long
Public Declare PtrSafe Function closesocket Lib "Ws2_32.dll" (ByVal socket As Long) As Long
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal length As Long)
Public Declare PtrSafe Function Send Lib "Ws2_32.dll" Alias "send" (ByVal s As Long, ByRef buf As Any, ByVal BufLen As Long, ByVal flags As Long) As Long
Public Declare PtrSafe Function SendWithPtr Lib "Ws2_32.dll" Alias "send" (ByVal s As Long, ByVal bufPtr As Long, ByVal BufLen As Long, ByVal flags As Long) As Long
Private Declare PtrSafe Function WSAGetLastError Lib "Ws2_32.dll" () As Long
Private Declare PtrSafe Function VarPtrArray Lib "VBE7" Alias "VarPtr" (var() As Any) As Long

Sub TestWinsock()
    Dim m_wsaData As wsaData
    Dim m_RetVal As Integer
    Dim m_Hints As ADDRINFO
    Dim m_ConnSocket As Long: m_ConnSocket = INVALID_SOCKET
    Dim Server As String
    Dim port As String
    Dim pAddrInfo As LongPtr
    Dim RetVal As Long
    Dim lastError As Long

    RetVal = WSAStartup(MAKEWORD(2, 2), m_wsaData)
    If (RetVal <> 0) Then
        LogError "WSAStartup failed with error " & RetVal, WSAGetLastError()
        Call WSACleanup
        Exit Sub
    End If

    m_Hints.ai_family = AF.AF_UNSPEC
    m_Hints.ai_socktype = sock_type.SOCK_STREAM
    Server = "localhost"
    port = "5001"

    RetVal = GetAddrInfo(Server, port, VarPtr(m_Hints), pAddrInfo)
    If (RetVal <> 0) Then
        LogError "Cannot resolve address " & Server & " and port " & port & ", error " & RetVal, WSAGetLastError()
        Call WSACleanup
        Exit Sub
    End If

    m_Hints.ai_next = pAddrInfo
    Dim connected As Boolean: connected = False
    Do While m_Hints.ai_next > 0
        CopyMemory m_Hints, ByVal m_Hints.ai_next, LenB(m_Hints)

        m_ConnSocket = ws_socket(m_Hints.ai_family, m_Hints.ai_socktype, m_Hints.ai_protocol)

        If (m_ConnSocket = INVALID_SOCKET) Then
            LogError "Error opening socket, error " & RetVal
        Else
            Dim connectionResult As Long

            connectionResult = connect(m_ConnSocket, m_Hints.ai_socktype, m_Hints.ai_addrlen)

            If connectionResult <> SOCKET_ERROR Then
                connected = True
                Exit Do
            End If

            LogError "connect() to socket failed"
            closesocket (m_ConnSocket)
        End If
    Loop

    If Not connected Then
        LogError "Fatal error: unable to connect to the server", WSAGetLastError()
        Call WSACleanup
        Exit Sub
    End If

    Dim SendBuf() As Byte
    SendBuf = StrConv("Message #1", vbFromUnicode)

    Dim BufLen As Integer
    BufLen = UBound(SendBuf) - LBound(SendBuf) + 1

    ' !!!!!!!!!!!
    ' !! Send() does not seem to send the right bytes !!
    ' !!!!!!!!!!!
    RetVal = Send(m_ConnSocket, SendBuf(0), BufLen, 0)

    ' The following does not work either:
    ' RetVal = SendWithPtr(m_ConnSocket, VarPtrArray(SendBuf), buflen, 0)
    If RetVal = SOCKET_ERROR Then
        LogError "send() failed", WSAGetLastError()
        Call WSACleanup
        Exit Sub
    Else
        Debug.Print "sent " & RetVal & " bytes"
    End If

    RetVal = closesocket(m_ConnSocket)
    If RetVal <> 0 Then
    LogError "closesocket() failed", WSAGetLastError()
    Call WSACleanup
    Else
        Debug.Print "closed socket"
    End If
End Sub

Public Function MAKEWORD(Lo As Byte, Hi As Byte) As Integer
MAKEWORD = Lo + Hi * 256& Or 32768 * (Hi > 127)
End Function

Private Sub LogError(msg As String, Optional ErrorCode As Long = -1)
    If ErrorCode > -1 Then
        msg = msg & " (error code " & ErrorCode & ")"
    End If

    Debug.Print msg
End Sub

 

 

3 Replies

Did you read the code? Or at least see these 2 comments:
Send() does not seem to send the right bytes !!
The following does not work either

So here is someone who understands the problem we're trying to solve, knows something about programming (e.g. as evidenced by use of PtrSafe and clear and consistent programming style), and they could not figure it out, yet.
The chances of someone in this forum looking at this and being able to provide the answer are near-zero.
I believe your best bet is to hire a competent developer to get this working for you. It might take a few days of work.

@Tom_van_Stiphout 

 

Thank you so much for your advice, but I loved if you point me where I can buy proper books that deals with these, I think it's now time to use books. Even if I find a proper developer what there some error at later stage it will mean calling that person.

 

So, learning how to do it on my own is the best because this is not a one-off project, however, many thanks for your advice.

Regarding the books you should search for books regarding advanced VB6 programming
One way to tackle this is to search on "each" piece of element along with some Internet archive searching.