Page 1 of 2 12 LastLast
Results 1 to 40 of 48

Thread: VB6 - Simple Sock

  1. #1

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,477

    VB6 - Simple Sock

    SimpleSock basically performs the same functions as NewSocket. Like NewSocket, it supports IPv6 as well as IPv4. This more or less restricts it's use to Windows Vista or better, as older operating systems do not support dual stack using "ws2_32.dll". Unlike NewSocket, it cannot be used as a Control Array because of the way it handles listening sockets (more on that later).

    While Emiliano Scavuzzo's subclassing technique remains fairly much intact, the rest of the program has been completely rewritten and hopefully simplified. Notifying the Class with the protocol being used (TCP/UDP) is no longer required. Instead there are separate routines to handle each task. Lets take a look at some of the basics.

    UDP (User Datagram Protocol)
    I started with this one because it is the simplest. UDP is a peer-to-peer protocol, because both parties are equal and either one can initiate the conversation. It is also connectionless. That is to say that data is just sent with no idea if it made it correctly to the other end. The packet size is also very limited (256 bytes). For these reasons, it is rarely used for sensitive bulk data. In the sample program provided, an instance of SimpleSock is created called "mSocket". "mSocket" defaults to IPv4, so if IPv6 is required, you must notify the instance by setting the mSocket.IPvFlg to 6. To initiate a UDP session, you simply call:
    Code:
    mSocket.UDPInit(Destination, PortConnect, PortLocal)
    The Destination Port and the Local Port are required, but if it is not known, the Destination can be left blank. This might be the case if the initial receiver does not know where the first message will be originating from. If blank, the GetAddrInfo function will return the LoopBack address (127.0.0.1 for IPv4 & ::1 for IPv6). You can test this functionality by setting the UDP option and the Local and Destination ports (they can both be the same), and typing a message in the text box followed by an <Enter>. The program will send the message to itself and the sender address (127.0.0.1/::1) will appear in the Destination text box. In the real world however, the sender's IP address will appear in the Destination text box, at which point the user can once again call the UDPInit function to update its information.

    So what information gets updated? The first time through, UPDInit creates the socket and binds it to the Local Port. It then creates a "sockaddr" for the destination using GetAddrInfo. The sockaddr structure is the part that gets updated. For those familiar with the original IPv4 structure, it looked like this:
    Code:
    Private Type sockaddr_in
        sin_family          As Integer  '2 bytes
        sin_port            As Integer  '2 bytes
        sin_addr            As in_addr  '4 bytes
        sin_zero(0 To 7)    As Byte     '8 bytes
    End Type                            'Total 16 bytes
    or reflected as:
    Private Type sockaddr
        sa_family           As Integer  '2 bytes
        sa_data(0 to 13)    As Byte     '14 bytes
    End Type                            'Total 16 bytes
    When IPv6 came along, this had to be changed to:
    Code:
    Private Type sockaddr_in6
        sin6_family         As Integer  '2 bytes
        sin6_port           As Integer  '2 bytes
        sin6_flowinfo       As Long     '4 bytes
        sin6_addr           As in6_addr '16 bytes
        sin6_scope_id       As Long     '4 bytes
    End Type                            'Total 28 bytes
    Private Type sockaddr
        sa_family           As Integer  '2 bytes
        sa_data(0 to 25)    As Byte     '26 bytes
    End Type                            'Total 28 bytes
    The larger sockaddr is used to carry the information for both IP protocols, with the extra 12 bytes being ignored for IPv4. Because the packet data is of limited length, UDP data is left in the Winsock Buffer and the calling program is informed of it's length. The calling program then recovers the data and empties the Winsock Buffer.

    To send data via UDP, we need the Socket Handle, the binary Data and it's length, and the sockaddr and it's length for the destination. The data is passed to the output buffer as string data and converted to byte data, or sent directly to the output buffer as byte data. Providing that the sockaddr has been updated correctly, all the information is available to send back to the other end with a call to mSocket.UDPSend.

    TCP (Transport Control Protocol)
    The more commonly used protocol is TCP. There are actually 2 types of TCP, because one end acts as the server, and one end acts as the client. Lets look at the client end first, because it is the simpler. We establish a connection with the other end by calling:
    Code:
    mSocket.TCPConnect(Destination, PortConnect)
    We supply the Destination as either an IP address or a domain name, and the destination port as a long variable. GetAddrInfo will find the IP address for a Domain name, provided the name is defined in a DNS host, or it is a local network name. Normally, the Local port is not required, as the API will find the first available port. SimpleSock however does have the ability to use a selected port. If the port selected is not being used, it will bind the created socket to the port. It also eliminates the TIME_WAIT period by setting the options "SO_LINGER" & "SO_REUSEADDR". For reasons unknown, I had to set both these options to achieve the desired result. The API will send out a SYN request to the other end, and wait for a response. If the other end is listening for a connection request, it will send a SYN_ACK back to us. The API will acknowledge this by sending an ACK, and the connection is established. Once the connection is established, a "Connect" event is fired back to the calling program, and data can be sent immediately using "TCPSend".

    Receipt of data is similar to UDP, except that SimpleSock removes the data from the Winsock buffer and adds it to it's own buffer. This is necessary because sent records can be quite lengthy, and are received in chunks. What is different about SimpleSock is the provision to handle encrypted data. This is accomplished by using 2 separate event messages (DataArrival/EncrDataArrival) to inform the calling program of data arrival.

    To act as a TCP server, the socket is created and bound to the selected port using:
    Code:
    mSocket.Listen(PortListen)
    When a connection request is received from the other end, the API sends an "FD_ACCEPT" message to the "PostSocket" routine. This is where SimpleSock differs from NewSocket and it predecessors. The older programs would create a new socket and a temporary instance of the class to handle it. It would then be registered as an "Accept" item, before firing off a "ConnectionRequest" event to the calling program. The calling program would then close the Listening socket and call the class "Accept" function with the new socket handle. Closing of the listening socket and de-registering it caused the Socket Collection to be destroyed and the Window closed. The new socket would then be registered as a normal socket (causing a new Window and Socket Collection to be created), ownership of the new socket transferred from the temporary Class to the original Class, and the temporary Class destroyed. The calling program would then create a new Listening Socket. If this all sounds very complicated, it was. But it was necessary in order to duplicate the way that the MS Winsock Control handled things when used as a Control Array.

    When SimpleSock receives an "FD_ACCEPT" message from an incoming connection attempt, it creates and registers the new socket as it normally would, and leaves the original listening socket intact. It then fires off a "ConnectionRequest" event to the calling program. The calling program then calls mSocket.Accept with the new socket handle. The Accept function saves the listening socket handle, sets a flag, and readies the new socket to receive and send data. If another connection request is received while the new socket is open, it will be ignored because the new socket is not in the listening mode. When the new socket is closed, the listening socket handle will be restored, and another connection request will be entertained.

    This simplified approach is only useful when using the SimpleSock Class directly. It will not be effective if it was made into a Control and used as a Control Array. The next step is to make the Class able to handle multiple connections on the same listening port without creating a Control.

    J.A. Coutts

    Note: When using Link Local IPv6 addresses to communicate with older systems such as Vista, you may have to add the interface (eg. %8) to the IP address.

    Note: The sample program is a demonstration program that uses various aspects of the socket function. It may not work properly when switching from one to another. Restart the program to test different functions.

    UPDATE: 11/28/2016
    An error was discovered in SimpleSock when it was being used for listening and a CloseSocket was initiated from within the class. This occurred when the connection to the remote socket was lost. The CloseSocket routine would send an Event message to the calling program, which in turn would call the CloseSocket routine. This caused the listening socket to be closed along with the connected socket.

    UPDATE: 07/08/2017
    GetIPFromHost and uInBuffer/uOutBuffer added

    UPDATE: 04/22/2017
    Bug fixes in DeleteByte & StrToByte

    UPDATE: 04/23/2022
    Attached Images Attached Images  
    Attached Files Attached Files
    Last edited by couttsj; Apr 23rd, 2022 at 05:42 PM.

  2. #2

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,477

    Re: VB6 - Simple Sock

    In order to handle multiple socket connections, we need to have multiple instances of the socket class. But we also need to fire Event messages back to the calling program for each socket. Unfortunately, VB does not allow us to use arrays of Classes with events. So we have to come up with a work around, and I think I found the answer here:

    http://www.vbforums.com/showthread.p...ays-of-objects

    I combined the code from penagate and Bonnie West with the Event calls that I needed. Rather than just supply the code, I thought it would be more beneficial to user understanding to go through the actual process.

    On a new project EXE, add a class module (defaults to Class1). Add the following to the Form1 Declarations:
    Code:
    Implements Class1
    Private mSocket() As New Class1
    Private Max_Connect As Long
    The Implements statement makes all methods declared in Class1 as Public, common across all Class1 instances. The other statement creates 6 instances of Class1.

    In the default Form1, add the following to the Load function:
    Code:
    Private Sub Form_Load()
        Dim lNum As Long
        Max_Connect = InputBox("Enter number of connections.", "CONNECTIONS", 5)
        ReDim Preserve mSocket(Max_Connect)
        For lNum = 0 To Max_Connect
            Set mSocket(lNum).Callback(lNum) = Me
        Next
    End Sub
    The use of the Set function will become evident later.

    Create a Command button called cmdTest to the form with the following code:
    Code:
    Private Sub cmdTest_Click()
        Dim lNum1 As Long
        Dim lNum2 As Long
        lNum1 = Int(((Max_Connect + 1) * Rnd)) 'Generate random interface number 0 to Max
        lNum2 = Int((8 * Rnd)) 'Generate random event number 0 to 7
        mSocket(lNum1).FireEvent lNum2
    End Sub
    This routine creates random interfaces and events, and calls the FireEvent routine in the applicable instance of the class. You will also need a multiline Textbox called Text1.

    In Class1, add the following to the Declaration section:
    Code:
    Option Explicit
    
    Private m_Callback As Class1
    Private m_Index    As Long
    and these methods:
    Code:
    Public Sub CloseSck(ByVal Index As Long)
    
    End Sub
    Public Sub Connect(ByVal Index As Long)
    
    End Sub
    Public Sub ConnectionRequest(ByVal Index As Long, ByVal requestID As Long)
    
    End Sub
    Public Sub DataArrival(ByVal Index As Long, ByVal bytesTotal As Long)
    
    End Sub
    Public Sub EncrDataArrival(ByVal Index As Long, ByVal bytesTotal As Long)
    
    End Sub
    Public Sub Error(ByVal Index As Long, ByVal Number As Long, Description As String, ByVal Source As String)
    
    End Sub
    Public Sub SendComplete(ByVal Index As Long)
    
    End Sub
    Public Sub SendProgress(ByVal Index As Long, ByVal bytesSent As Long, ByVal bytesRemaining As Long)
    
    End Sub
    These empty sub routines will create methods in Form1.Class1, but have to be activated. To accomplish this, simply click on each one. As you do, the method name will display in bold. The empty Public methods in Class1 act together with the Private methods in Form1, and must be used together.

    Now you need to add code to these newly created routines in Form1.
    Code:
    Private Sub Class1_CloseSck(ByVal Index As Long)
        Dim sMsg As String
        sMsg = "Interface:" & CStr(Index) & ", CloseSck"
        Text1.Text = Text1.Text & sMsg & vbCrLf
        Debug.Print sMsg
    End Sub
    
    Private Sub Class1_Connect(ByVal Index As Long)
        Dim sMsg As String
        sMsg = "Interface:" & CStr(Index) & ", Connect"
        Text1.Text = Text1.Text & sMsg & vbCrLf
        Debug.Print sMsg
    End Sub
    
    Private Sub Class1_ConnectionRequest(ByVal Index As Long, ByVal requestID As Long)
        Dim sMsg As String
        sMsg = "Interface:" & CStr(Index) & ", ConnectionRequest on socket " & CStr(requestID)
        Text1.Text = Text1.Text & sMsg & vbCrLf
        Debug.Print sMsg
    End Sub
    
    Private Sub Class1_DataArrival(ByVal Index As Long, ByVal bytesTotal As Long)
        Dim sMsg As String
        sMsg = "Interface:" & CStr(Index) & ", DataArrival  " & CStr(bytesTotal) & " bytes"
        Text1.Text = Text1.Text & sMsg & vbCrLf
        Debug.Print sMsg
    End Sub
    
    Private Sub Class1_EncrDataArrival(ByVal Index As Long, ByVal bytesTotal As Long)
        Dim sMsg As String
        sMsg = "Interface:" & CStr(Index) & ", EncrDataArrival  " & CStr(bytesTotal) & " bytes"
        Text1.Text = Text1.Text & sMsg & vbCrLf
        Debug.Print sMsg
    End Sub
    
    Private Sub Class1_Error(ByVal Index As Long, ByVal Number As Long, Description As String, ByVal Source As String)
        Dim sMsg As String
        sMsg = "Interface:" & CStr(Index) & ", Error: " & CStr(Number) & ", " & Description & " in " & Source
        Text1.Text = Text1.Text & sMsg & vbCrLf
        Debug.Print sMsg
    End Sub
    
    Private Sub Class1_SendComplete(ByVal Index As Long)
        Dim sMsg As String
        sMsg = "Interface:" & CStr(Index) & ", SendComplete"
        Text1.Text = Text1.Text & sMsg & vbCrLf
        Debug.Print sMsg
    End Sub
    Now we need to define the CallBack routines in Class1, and a way to generate the Event messages. Using the instructions provided by Bonnie West, these are declared as Friend to prevent them from being universally implemented across all Class1 instances.
    Code:
    Friend Property Get Callback(Optional ByVal Index As Long) As Class1
        Set Callback = m_Callback
    End Property
    
    Friend Property Set Callback(ByVal Index As Long, ByRef RHS As Class1)
        m_Index = Index
        Set m_Callback = RHS
    End Property
    
    Friend Sub FireEvent(ByVal lEvent As Long)
        Debug.Assert Not m_Callback Is Nothing      'If code stops here,
            'the Callback property must be set first!
        Select Case lEvent
            Case 0
                Call m_Callback.CloseSck(m_Index)
            Case 1
                Call m_Callback.Connect(m_Index)
            Case 2
                Call m_Callback.ConnectionRequest(m_Index, 12345)
            Case 3
                Call m_Callback.DataArrival(m_Index, 100)
            Case 4
                Call m_Callback.EncrDataArrival(m_Index, 200)
            Case 5
                Call m_Callback.Error(m_Index, 56238, "Test Error", "Fire Event")
            Case 6
                Call m_Callback.SendComplete(m_Index)
            Case 7
                Call m_Callback.SendProgress(m_Index, 1000, 5000)
        End Select
    End Sub
    J.A. Coutts
    Last edited by couttsj; May 7th, 2017 at 05:28 PM.

  3. #3
    Fanatic Member
    Join Date
    Aug 2016
    Posts
    678

    Re: VB6 - Simple Sock

    I hope YOUR sock is very Strong . if used for other people , we dont like have bugs. have you user this for project is perfect? i find you have post many
    threads about sock. I have been confused

  4. #4

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,477

    Re: VB6 - Simple Sock

    Quote Originally Posted by xxdoc123 View Post
    I hope YOUR sock is very Strong . if used for other people , we dont like have bugs. have you user this for project is perfect? i find you have post many
    threads about sock. I have been confused
    NewSocket V2.5 is very stable, and has been used by myself in many applications. SimpleSock is a completely rewritten socket program, and there will likely be bugs, especially when I add the ability to handle multiple sockets.

    J.A. Coutts

  5. #5
    Fanatic Member
    Join Date
    Aug 2016
    Posts
    678

    Re: VB6 - Simple Sock

    good .can you post some pictures about your projects who usede newsocket2.5? hh

  6. #6

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,477

    Re: VB6 - Simple Sock

    Quote Originally Posted by xxdoc123 View Post
    good .can you post some pictures about your projects who usede newsocket2.5? hh
    In Advanced Search, select Single Content Type and search for NewSocket in CodeBank - Visual Basic 6 and earlier.
    J.A. Coutts

  7. #7
    Fanatic Member
    Join Date
    Aug 2016
    Posts
    678

    Re: VB6 - Simple Sock

    i know .i searched and download all your sock project. but i used xp.so i must modiy some code .now all can used in xp..good job.thanks. but i cant know how can used them for where.o.ye

  8. #8

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,477

    Re: VB6 - Simple Sock

    Quote Originally Posted by xxdoc123 View Post
    i know .i searched and download all your sock project. but i used xp.so i must modiy some code .now all can used in xp..good job.thanks. but i cant know how can used them for where.o.ye
    As I said in the very beginning:
    -----------------------------------------------------------
    Like NewSocket, it supports IPv6 as well as IPv4. This more or less restricts it's use to Windows Vista or better, as older operating systems do not support dual stack using "ws2_32.dll".
    -----------------------------------------------------------
    It will not work on XP.

    J.A. Coutts

  9. #9
    Fanatic Member
    Join Date
    Aug 2016
    Posts
    678

    Re: VB6 - Simple Sock

    I know. I fixed.hh

  10. #10
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: VB6 - Simple Sock

    The way software like this gets stronger and more reliable is for more people to make more use of it. That way bugs get found and fixed (if people report them), object models can be improved, and useful features incorporated as the need is uncovered. This also can result in more motivation to improve documentation.

    I'm not a fan of forking such projects. Where possible I like to see a strong main branch be reinforced. It helps if the project is focused on a specific need and doesn't try to do too much, but sometimes it can still be necessary to fork now and then.

    It looks like a lot of hard work has been invested here.

  11. #11

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,477

    Re: VB6 - Simple Sock

    Attached is a version of SimpleSock (called SimpleServer) that supports multiple sockets using Implements. It is my feeling that there should be 2 versions, one that supports single use client sockets, and one that supports server type applications. ServerSock is capable of doing everything that SimpleSock does, but it is not quite as simple and easy to use. Each socket that you would want to create would mean managing an array element, rather than a different instance name. I could use some feed back on this.

    I also need a way to stress test this server program, as I have no idea how many sockets it will handle. I have a Pseudo SMTP server running on a Windows 2000 server that uses the original cSocket Control. I have not been able to upgrade it because 2000 does not support IPv6. It handles a maximum of 25 sockets, and occasionally it crashes at high volume. Because it runs as a service, I got around the problem by instructing the Service Manager to restart it. I would like to find out how many sockets this new program will handle. Feedback is welcome.

    CAUTION: Both of these programs (SimpleSock & SimpleServer) are in their infancy and may contain bugs.

    J.A. Coutts
    Attached Images Attached Images  
    Attached Files Attached Files
    Last edited by couttsj; Nov 19th, 2016 at 02:04 PM.

  12. #12
    Fanatic Member
    Join Date
    Aug 2016
    Posts
    678

    Re: VB6 - Simple Sock

    if used xp

    Name:  xp.jpg
Views: 6721
Size:  14.9 KB
    Last edited by xxdoc123; Nov 16th, 2016 at 10:53 PM.

  13. #13

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,477

    Re: VB6 - Simple Sock

    Quote Originally Posted by xxdoc123 View Post
    if used xp
    Good work xxdoc123. It looks like the problem with XP is it's lack of support for the "inet_ntop" function. I also assume, since you made no changes to the IPv6 portion of the code, that IPv6 does not function on XP after loading and registering "ws2_32.dll". Perhaps the best solution is to just use "inet_ntoa" for all IPv4 functions, and "inet_ntop" for IPv6 functions. To do that, add the declaration:
    Code:
    Private Declare Function inet_ntoa Lib "ws2_32.dll" (ByVal iaddr As Long) As Long
    to the class, and change:
    Code:
    lRet = inet_ntop(AF_INET, Sin4.sin_addr, bBuffer(0), INET_ADDRSTRLEN)
    to:
    Code:
    lRet = inet_ntoa(Sin4.sin_addr.s_addr)
    The rest of the code changes you made appear to be unnecessary.

    J.A. Coutts

  14. #14
    Fanatic Member
    Join Date
    Aug 2016
    Posts
    678

    Re: VB6 - Simple Sock

    i dont used ipv6,and i.m newbie.
    i have two computers,one used win7 ,the other used xp.

  15. #15
    Fanatic Member
    Join Date
    Aug 2016
    Posts
    678

    Re: VB6 - Simple Sock

    i dont used ipv6,and i.m newbie.
    i have two computers,one used win7 ,the other used xp.

  16. #16
    Fanatic Member
    Join Date
    Aug 2016
    Posts
    678

    Re: VB6 - Simple Sock

    i dont used ipv6,and i.m newbie.
    i have two computers,one used win7 ,the other used xp.

  17. #17

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,477

    Re: VB6 - Simple Sock

    After xxdoc123 informed us about how to make XP work, I decided to update the SMTP Pseudo Server with the new SimpleServer class (attached). Because spammers don't exactly play by the rules, it turned out to be an excellent test bench.

    1. SMTP standards call for each command to be followed by CrLf, but some spammers only use a Cr.
    2. SMTP software should wait for each command response, but some spammers don't pay any attention to incoming data, and just keep on sending data.
    3. A 500 level response from the server indicates a fatal error, and senders should terminate the connection. Some spammers don't do that, or improperly end the connection.

    During testing, I believe that problem 3 above caused the API to return an error 10053 (Software caused connection abort). Also, while sending data, Error 10054 (Connection reset by peer) would be generated. Either of these conditions would leave the socket state as "sckerror", and this state would leave the socket unusable because it was not "sckClosed". Since "sckerror" effectively means that the socket is available, the software was changed to use the socket in either case.

    The attached program runs on the desktop with the incoming commands displayed in a textbox, but the real program will be designed to run as a Service. As such, there is no practical way of monitoring its status. Therefore, a single listening socket on port 26 was added using SimpleSock. This allows an external monitor (whether local or remote) to connect and receive the same data that is being added to the log file. This particular part of the program has not been tested yet.

    J.A. Coutts

    Note: The attached program works on older systems because it does not use the TCPConnect function. Older systems do not support "GetAddrInfo", and when it is attempted you will get an "Entry Point Not Found" error.
    Attached Images Attached Images  
    Attached Files Attached Files
    Last edited by couttsj; Nov 29th, 2016 at 12:11 PM.

  18. #18
    Fanatic Member
    Join Date
    Aug 2016
    Posts
    678

    Re: VB6 - Simple Sock

    i very like your work about winsock or other http projects .

  19. #19

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,477

    Re: VB6 - Simple Sock

    Reusing a socket in the "sckerror" condition only solved part of the problem. Because the socket was never closed properly, it was never deleted from the subclassing collection, resulting in what is commonly known as a "memory leak". The problem originates here with a 10053 error:
    Code:
    Private Sub PostSocket(ByVal lEventID As Long, ByVal lErrorCode As Long)
        'This procedure is called by the WindowProc callback function
        'from the modSocket module. The lEventID argument is an ID of the
        'network event that occurred for the socket. The lErrorCode
        'argument contains an error code only if an error was occurred
        'during an asynchronous execution.
        If lErrorCode <> 0 Then
            m_State = sckError
            Call PrintDebug("STATE: sckError")
            Call m_Callback.Error(m_Index, lErrorCode, GetErrorDescription(lErrorCode), "Windows Message")
            Exit Sub
        End If
    When I connected remotely to the SMTP Pseudo Server program after it had been running for a while, it reported 47 sockets in use. However, when I examined the network status with a "netstat -an" command, there was only the listening socket in use. Examining the log file, I found 46 10053 errors.

    I looked back to see how cSocketMaster handled it, and it was the same. However, when I looked back at CSocket by Oleg Gdalevich, he destroyed the socket, but left it in the "sckerror" state. I have to wonder what the point is of leaving the socket in that state. Why not just report the error and close the socket? What am I missing?

    J.A. Coutts

    Addendum: I was able to duplicate the 10053 error by ending a connected program without closing the socket itself. The correct way was to close the socket in the Unload event.
    Last edited by couttsj; Nov 18th, 2016 at 03:32 PM.

  20. #20

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,477

    Re: VB6 - Simple Sock

    Ran into another problem during testing of SMTPServer. This one however doesn't relate to either class or the module, but is directly related to the spam traffic itself, and is handled in the form.

    Occasionally, a connection from the spammer just stays connected. I assume that is because the spammer's script failed, but I am just guessing. Whatever the cause, it takes that particular socket out of commission. So I added a time check on connected sockets to the GetNextSocket routine. If a connection is idle for more than 30 seconds, it is automatically closed.

    I have updated all the download files with the fixes made so far.

    J.A. Coutts

  21. #21

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,477

    Re: VB6 - Simple Sock

    After several days of testing the SMTPServer on the desktop, I have converted it to run as a service. If there is an interest, I will publish it in a separate post.

    J.A. Coutts

  22. #22
    Fanatic Member
    Join Date
    Aug 2016
    Posts
    678

    Re: VB6 - Simple Sock

    i have no web sevsre computer to test you project.

  23. #23
    Lively Member
    Join Date
    Oct 2008
    Posts
    123

    Re: VB6 - Simple Sock

    Hi couttsj
    sorry for question.
    Could you post an example of how to use your SMTP servers?
    Thanks for your effort

  24. #24

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,477

    Re: VB6 - Simple Sock

    Quote Originally Posted by Nanni View Post
    Hi couttsj
    sorry for question.
    Could you post an example of how to use your SMTP servers?
    Thanks for your effort
    It is more correctly called an SMTP Pseudo Server, because it does not actually send or receive email. It was implemented on our server many years ago because our server was being bombarded by 10,000 to 15,000 connection attempts per day on port 25, and we had limited bandwidth. That was with no "MX" record. When no "MX" record was found, they would just use the "A" record, which is allowed by SMTP standards. So we added an "MX" record, and implemented the Pseudo Server. That cut down the connection attempts to about 300 per day.

    By trial and error, we discovered the best method to discourage spammers was to quit the connection after the "MAIL FROM:". Waiting for the "RCPT TO:" just caused the spammers to repeatedly try different addresses. Dropping the connection before that just caused them to keep connecting. Over the years we had to make adjustments, as the spammers kept trying to work around it. One enterprising spammer kept using a "RESET" command to try different "MAIL FROM:"s. Every once in a while a spammer will send hundreds of "AUTH LOGIN" commands in an attempt to guess a UserID & Password. Limiting the number of sockets available discourages that kind of activity.

    J.A. Coutts
    Last edited by couttsj; Nov 21st, 2016 at 01:08 PM.

  25. #25

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,477

    Re: VB6 - Simple Sock

    SimpleSock has been updated. See update message at the bottom of the first post.

    J.A. Coutts

  26. #26

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,477

    Re: VB6 - Simple Sock

    The attached program demonstrates the use of Unicode, as well as the use of a record header. The following functions have been added to SimpleSock:
    uInBuffer
    uOutBuffer
    ByteToUni
    UniToByte
    The use of a header required working at the byte level to add the Record Header and the use of bOutBuffer. On input, the data is recovered from uOutBuffer, the header is stripped after recovering the Record Length, and the message recovered as a Unicode string (double-wide characters).

    The same program can be used for both ends of the conversation. Start one and choose the server option. Then add a listening port and click "Listen". Start the second one and use the defaults. Enter the loopback address (127.0.0.1) and the port to connect to. Then click "Connect".

    The Header that I am using consists of 8 bytes, although it can be of any length as long as it is evenly divisible by 2. When using byte values only, you can use any length.
    byte(0) = RecType
    byte(1) = VerMaj
    byte(2) = VerMin
    byte(3) = Reserved
    byte(4) = Reserved
    byte(5) = Reserved
    byte(6) = RecLen(high order)
    byte(7) = RecLen(low order)
    The use of RecType allows for different types of records to be handled differently (eg. encrypted/non-encrypted), and Major and Minor Version numbers are self explanatory.

    There is one possible problem with this approach, which I have not tested. When the incoming data is transferred to a Unicode string, if one of the problem characters above "&H7F" is encountered in the length, and the user is using a non-Latin character set, it could get converted by the operating system into an "&H3F".

    J.A. Coutts
    Attached Images Attached Images  
    Attached Files Attached Files

  27. #27
    Fanatic Member
    Join Date
    Aug 2016
    Posts
    678

    Re: VB6 - Simple Sock

    i download the project.test is good.thanks
    Last edited by xxdoc123; Dec 13th, 2016 at 08:56 PM.

  28. #28

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,477

    Re: VB6 - Simple Sock

    This version of SampleSock (SampleSock2.vbp) uses encryption, but otherwise works the same as the previous version. It requires my encryption library available here:
    http://www.yellowhead.com/documents/jcrypt.dll

    The program acting as the client creates a Public/Private ECC (Elliptical Curve Cryptography) Key pair, connects to the program acting as the listening server, and sends the Public Key along with the User name as a Record Type 1 (Client Hello).

    The server receives the Client Hello, extracts the User Name and Client Public Key, and creates it's own Public/Private ECC Key pair. It then uses the Client Public Key and it's own Private Key to create a Shared Secret. It's own Public Key and user name are then sent back to the client as a Record Type 2 (Server Hello).

    The client receives the Server Hello and extracts the User Name and the Server Public Key. The Server Public Key and it's own Private Key are combined to create the same Shared Secret that the server created.

    Any further traffic is encrypted/decrypted using the Shared Secret as the key (Record Type 8). Although the traffic is encrypted, it cannot be considered totally secure because anyone can connect to the listening socket and pretend to be a known user. The next step is to add NAT Traversal using a third party server. This server would require proper authentication, as evidenced by the provision for a Record Type 4 (Encrypted Password).

    J.A. Coutts
    Attached Files Attached Files

  29. #29

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,477

    Re: VB6 - Simple Sock

    A word of caution is advised when disabling the TIME_WAIT by setting the options "SO_LINGER" & "SO_REUSEADDR". It appears to change the way that a socket disconnects. The normal disconnect uses the following sequence:
    Client --> SYN --> Server
    Client <-- ACK/SYN <-- Server
    Client --> ACK --> Server
    Client --> ACK/PSH --> Server (Data)
    Client <-- ACK <-- Server
    Client --> ACK/FIN --> Server
    Client <-- ACK <-- Server
    Client <-- ACK/FIN <-- Server
    Client --> ACK --> Server

    With the TIME-WAIT disabled, the following sequence is observed:
    Client --> SYN --> Server
    Client <-- ACK/SYN <-- Server
    Client --> ACK --> Server
    Client --> ACK/PSH --> Server (Data)
    Client <-- ACK <-- Server
    Client --> ACK/RST --> Server

    When the Client uses the FIN, it is saying that I have no more data to send and waits for a response in the TIME-WAIT period. When it sends an RST, it is saying that something went wrong and I am terminating the connection immediately. The server interprets this as an error 10053 and closes the socket. Spammers use the RST quite frequently so they can reuse the socket to pump out more garbage.

    J.A. Coutts

  30. #30

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,477

    Re: VB6 - Simple Sock

    SimpleSock has been updated. A function called GetIPFromHost was added. This function permits a DNS lookup on a domain without making a connection. As well, the Unicode buffers (uInBuffer/uOutBuffer) were permanently added.

    J.A. Coutts

  31. #31

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,477

    Re: VB6 - Simple Sock

    Another bug was discovered in SimpleSock. The original StrToByte routine was designed to automatically detect the use of Unicode wide characters and default to convert all bytes instead of every second one. Some email clients use special formatting wide characters such as ̡٪. Email standards only support ASCII characters, and replying to messages containing these characters caused the message to fail.

    Since SimpleSock now includes Unicode buffers, this feature is no longer required and was removed.

    J.A. Coutts

  32. #32
    Lively Member
    Join Date
    Apr 2009
    Posts
    73

    Re: VB6 - Simple Sock

    I figured out why SimpleSock didn't work same as NewSocket2.5

    In the function

    Public Function Accept(requestID As Long) As Boolean

    Commented out

    'If m_State <> sckListening Then
    ' RaiseEvent Error(sckInvalidOp, "Socket is not in the listening mode", Routine)
    ' API_CloseSocket requestID
    ' Exit Function
    'End If

    because when Listening socket gets a ConnectionRequest with requestId

    The socket that accepts the connection (a new SimpleSock) isn't in Listening mode.
    It's suppose to hold the connection that the Listener sent in the ConnectionRequest and never act as another server.

    Also to
    Public Function Accept(requestID As Long) As Boolean
    in the end of the Else statement add
    RaiseEvent Connect

    Still can't figure out why my new socket that accepted the connection doesn't get any DataArrival events.
    Because as soon as it connects the server sends data to the client, so it should trigger that event.

    Seems as though the SOCKET_MESSAGE is never sent with FD_READ. OR the socket is never Registered from the Accept.

    Figured it out.. blnEvents is set to false for my socket.
    Found it.. the RegisterSocket had the blnEvents parameter to false
    Code:
    Call modSocket.RegisterSocket(m_hSocket, ObjPtr(Me), False)
    Fixed it
    Code:
    Call modSocket.RegisterSocket(m_hSocket, ObjPtr(Me), True)
    So the full new fix is
    Code:
    Public Function Accept(requestID As Long) As Boolean
        Const Routine As String = "SimpleSock.Accept"
        Call PrintDebug("STATE: " & CStr(m_State))
        'If m_State <> sckListening Then
        '    RaiseEvent Error(sckInvalidOp, "Socket is not in the listening mode", Routine)
        '    API_CloseSocket requestID
        '    Exit Function
        'End If
        m_hListen = m_hSocket 'Save listening socket handle
        m_hSocket = requestID 'Use the handle created by FD_ACCEPT message
        m_Protocol = SCK_TCP
        Call ProcessOptions
        If IsSocketRegistered(requestID) Then
            RaiseEvent Error(sckBadState, "Wrong protocol or connection state for the requested transaction or request", Routine)
            Exit Function
        Else
            m_bAcceptClass = True
            m_State = sckConnected
            Call PrintDebug("STATE: sckConnected")
            Call modSocket.RegisterSocket(m_hSocket, ObjPtr(Me), True)
            RaiseEvent Connect
        End If
        Accept = True
    End Function
    Now I get data for all my sockets, but it crashes as soon as I send some data.. by crashing I mean my whole visual basic IDE crashes.
    https://www.youtube.com/watch?v=4GqzwD5HrpU

    Here is a better video:
    https://www.youtube.com/watch?v=ucf5U7bTqNw


    I still can't figure out why SendTCP with Socket.bOutBuffer causes my IDE to crash.

    I guess I'm not using bOutBuffer the correct way? do I need to use CopyMemory on it?
    Last edited by pkedpker; Mar 18th, 2020 at 02:03 AM.

  33. #33

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,477

    Re: VB6 - Simple Sock

    To quote my original post:
    ---------------------------------------
    When SimpleSock receives an "FD_ACCEPT" message from an incoming connection attempt, it creates and registers the new socket as it normally would, and leaves the original listening socket intact. It then fires off a "ConnectionRequest" event to the calling program. The calling program then calls mSocket.Accept with the new socket handle. The Accept function saves the listening socket handle, sets a flag, and readies the new socket to receive and send data. If another connection request is received while the new socket is open, it will be ignored because the new socket is not in the listening mode. When the new socket is closed, the listening socket handle will be restored, and another connection request will be entertained.
    ---------------------------------------
    To accept multiple connections on the same listening socket, you must use SimpleServer:
    http://www.vbforums.com/showthread.p...B-SimpleServer

    J.A. Coutts

  34. #34
    Lively Member
    Join Date
    Apr 2009
    Posts
    73

    Re: VB6 - Simple Sock

    I thought the SimpleServer was outdated because the size of the SimpleSock was smaller and the dates were older. This one also has Listen/Bind so I figured I could also use it as server code.

    I found out my crashes are because I was using Property wrong.. I guess I was changing the address of the Property to a byte array which caused the crash.. now I set it up properly and it still doesn't even run.



    I guess I was doing it correctly when I did

    Socket.bOutBuffer = packet
    and not
    Socket.bOutBuffer(packet)

    one crashes and the other doesn't work..

    Fixed the crash by copying the packet() as Byte to a new packetCopy() as Byte.. seems you can't use it directly.

    Code:
        Dim packetCopy() As Byte
        ReDim packetCopy(UBound(packet))
        CopyMemory packetCopy(lLen1), packet(0), UBound(packet) + 1
    It looks like it all works.. but every 15 seconds my sockets just close and lose connection for no reason.. then after a minute the whole program just crashes again lol.
    Last edited by pkedpker; Mar 18th, 2020 at 02:57 PM.

  35. #35

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,477

    Re: VB6 - Simple Sock

    Quote Originally Posted by pkedpker View Post
    I thought the SimpleServer was outdated because the size of the SimpleSock was smaller and the dates were older. This one also has Listen/Bind so I figured I could also use it as server code.
    SimpleServer & SimpleSock are partner programs. SimpleServer is more complex and supports a socket array. It could be used for all socket connections, but it is unnecessarily complex for single socket connections. SimpleSock was developed first, and SimpleServer took much more time to develop. There were subsequent bug fixes implemented on both programs, but SimpleSock was never intended to be used for multiple connections, as you cannot separate the buffers without using an array.

    J.A. Coutts

  36. #36
    Lively Member
    Join Date
    Apr 2009
    Posts
    73

    Re: VB6 - Simple Sock

    I store 3 Socket's in a Class (clsUser) and everytime a new user is added to Users Collection it would create.
    Code:
    Set SocketA = New SimpleSock
    Set SocketB = New SimpleSock
    Set SocketC = New SimpleSock
    In each class

    Anyways I got it all working and disconnecting isn't a problem anymore it was a bug in my connection everything is okay now.

    Thanks for the code.. Before this I was using cSocket2.. and it crashed on start-up so I had to find a alternative.

  37. #37
    Member
    Join Date
    Dec 2011
    Location
    Stockholm, Sweden
    Posts
    45

    Re: VB6 - Simple Sock

    I had some problems with using CloseSocket after a connection had been established. As far as I understand I have to do it twice to close both the connected socket and then the remaining listening one. I was unable to get a new socket listening.
    It worked better after modifying the function CloseSocket like below. Is there any reason this is a bad idea?

    Code:
    Public Function CloseSocket() As Boolean
        Const Routine As String = "SimpleSock.CloseSocket"
        Dim lErrorCode As Long
        Dim lRet As Long
        Dim bTmp() As Byte
        If Not m_hSocket = SOCKET_ERROR Then
            lRet = API_CloseSocket(m_hSocket)
            If lRet = -1 Then
                m_State = sckError
                lErrorCode = Err.LastDllError
                RaiseEvent Error(lErrorCode, "Could not Close Socket!", Routine)
            Else
                Call modSocket.UnregisterSocket(m_hSocket)
                m_hSocket = SOCKET_ERROR
                RaiseEvent CloseSck
                CloseSocket = True
                If m_bAcceptClass Then
                    m_hSocket = m_hListen
                    m_State = scklistening
                    Call PrintDebug(CStr(m_hSocket) & ": scklistening")
                    m_bAcceptClass = False
                Else
                    m_State = sckClosed
                    Call PrintDebug("STATE: sckClosed")
                    m_sLocalIP = vbNullString
                    m_sRemoteHostIP = ""
                End If
                
                m_bRecvBuffer = bTmp
                m_bSendBuffer = bTmp
                m_lSendBufferLen = 0
                m_lRecvBufferLen = 0
            End If
        End If
    End Function

  38. #38

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,477

    Re: VB6 - Simple Sock

    Quote Originally Posted by TomasEss View Post
    I had some problems with using CloseSocket after a connection had been established. As far as I understand I have to do it twice to close both the connected socket and then the remaining listening one. I was unable to get a new socket listening.
    It worked better after modifying the function CloseSocket like below. Is there any reason this is a bad idea?
    Unlike most of the other functions, the CloseSocket function should not be called directly from the calling program. It should be called from the .CloseSck function in the calling program. The reason for this is that a socket close can be initiated from either end, from the client or from the server. When closed from the client end, the socket state is first changed to "sckClosing", an event is triggered to the .CloseSck function in the calling routine, and a call to CloseSocket completes the transaction. Once a socket is closed, any extra CloseSocket calls are ignored.

    The listening socket does not need to be closed at all. When a working socket is connected, the listening socket still exists but the handle is not accessible, so any new connection attempt is ignored. When the working socket is disconnected, the handle to the listening socket is restored, and a new working socket can once again be connected. The listening socket only needs to be disconnected when the program is exited. If you don't close it on exit, it will remain listening for an extended period of time.

    J.A. Coutts

  39. #39
    Member
    Join Date
    Dec 2011
    Location
    Stockholm, Sweden
    Posts
    45

    Re: VB6 - Simple Sock

    I understand, but you assume the server side will not disconnect/close the socket during runtime. What if it is not the client side that wants to disconnect? What if the server side wants to disconnect and then later start listening. Maybe on another port? In contrast to what you assume your sample includes a "Disconnect" button that can be used both when running as a server and client. When using it it actually calls the closesocket function (also when running as server). But if only clicked once, with a connection established, it is not possible to start listening again. It will give you: "ERROR -1: in SimpleSock.Listen, Unknown error."
    Clicking it twice will enable the sample running a server to start listening again.

  40. #40

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,477

    Re: VB6 - Simple Sock

    Quote Originally Posted by TomasEss View Post
    I understand, but you assume the server side will not disconnect/close the socket during runtime. What if it is not the client side that wants to disconnect? What if the server side wants to disconnect and then later start listening. Maybe on another port? In contrast to what you assume your sample includes a "Disconnect" button that can be used both when running as a server and client. When using it it actually calls the closesocket function (also when running as server). But if only clicked once, with a connection established, it is not possible to start listening again. It will give you: "ERROR -1: in SimpleSock.Listen, Unknown error."
    Clicking it twice will enable the sample running a server to start listening again.
    Straight from the download:
    Code:
    Private Sub cmdDisconnect_Click()
        Call mSocket_CloseSck
    End Sub
    J.A. Coutts

Page 1 of 2 12 LastLast

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