Search code examples
vb6winsockwinsockets

VB6 TCP IP Communication without Doevents or subclassing


What I need to happen with a VB6 application I maintain is the following.

  1. Establish a connection to a known address and port over a Ethernet network.
  2. Send a request

  3. Wait for a response.

I tried using WinSock and Winsock replacement but they all rely in one form or another the messaging loop inherent in various Windows application. I don't know enough about the Winsock API how to implement the above algorithm in VB6 (or in any other language.

My application is a VB6 CAD/CAM software that controls metal cutting machines over a dedicated Ethernet network. The software has been maintain for 20 years and we developed several driver for different types of motion controllers. To date the API for these motion controllers consist of

  1. Opening a connection to the hardware
  2. Sending a request to the hardware (for example Position of an axis)
  3. Waiting for a response (usually occurs in milliseconds).

Some of these controller work over a Ethernet Network but until now I never had to directly interact with the ports. I used the company supplied libraries to handle things. And they work in the way I mentioned above and throw a timeout error if a response doesn't occur in some defined time.

The problem with Winsock is that I have to insert DoEvents to get it a respond. This causes havoc with how we handle multi-tasking in our VB6 application. The replacement like CSocketMaster use subclassing which also cause havoc with our multi-tasking.

So any help on how to use the Winsock API or a third party dll that can do what I need to do as outlined above. I wouldn't be asking if I haven't seen other motion control do what I want to do.


Solution

  • I think it is rare for it to be appropriate to do networking synchronously, however this isn't networking in the traditional sense. This is a wire from a PC to a controller. This is like a string between two cans. In this case with a large old program, the most appropriate approach is the one that works the best and is the easiest to maintenance. < /end2cents >

    If VB6 + Winsock isn't working out for you, writing this in .NET and building it into a COM visible DLL for your VB6 program will fit the bill.

    The example below will get you started. If you do more than the occasional call to this, it will be slow as it opens and closes the connection on each call. It should be easy to expand it to allow for reusing an open connection for back and forth communication between the PC and controller. Just be careful that you don't create a memory leak!

    /// <summary>
    /// Sends a message to the specified host:port, and waits for a response
    /// </summary>
    public string SendAndReceive(string host, int port, string messageToSend, int millisecondTimeout)
    {
        try
        {
            using (var client = new TcpClient())
            {
                client.SendTimeout = client.ReceiveTimeout = millisecondTimeout;
                // Perform connection
                client.Connect(host, port);
    
                if (client.Connected)
                {
                    using (var stream = client.GetStream())
                    {
                        // Convert the message to a byte array
                        var toSend = Encoding.ASCII.GetBytes(messageToSend);
    
                        // Send the message
                        stream.Write(toSend, 0, toSend.Length);
    
                        // Get a response
                        var response = new byte[client.ReceiveBufferSize];
                        stream.Read(response, 0, client.ReceiveBufferSize);
    
                        return Encoding.ASCII.GetString(retVal);
                    }
                }
                else
                {
                    return null;
                }
            }
        }
        catch
        {
            return null;
        }
    }