Intro to Winsock Programming - with the SocketWrench OCX

By Brian McGinnis

Posted March 1 1999

Printer-friendly version

Download the source 

Introduction:

Many of us have used various techniques over the years to perform some sort of basic "Inter-Application" communication. For example, we might set up a shared file that all applications can see, then have each application check it periodically to see if it should perform some function. Direct Application-to-Application communication across different PCs, however, has generally required an in-depth knowledge of network protocols and a slug of low-level API calls.

The Internet's popularity has heightened the demand for this kind of communication, allowing applications running in different sites to communicate with each other on a demand basis. These applications can give immediate feedback on the status of the communication, and don't have to be limited to polling shared files. Shared files can also be a problem on the Internet where hosts of various operating systems are deployed and connections may just be demand-dialed.

Although we can certainly access the Winsock API from inside our Clarion programs, this kind of low-level programming is in contrast to the high level approach we are used to taking with application development inside the Clarion environment.

SocketWrench to the Rescue:

Catalyst Development Corporation has produced a toolkit that really approaches TCP/IP programming from a high-level standpoint. The toolkit, called SocketTools, is a Swiss army knife of networking components. One component, SocketWrench is available free of charge for development and distribution. SocketWrench provides high-level access to the Winsock API and it's great way to get started with Winsock programming. You can visit Catalyst's web site at: www.catalyst.com

Demo Applications:

I have provided two .APP files in the demo that can talk to each other via TCP/IP. The demos show one method that two applications can use to communicate with one another. These applications can be on the same machine or on two different machines that are connected via a TCP/IP network including the Internet.

The demo apps were created with Clarion 4b and the SocketWrench custom control version 2.2. No custom templates, classes, or any other 3rd party tools were used, so all of the code used is displayed in the various embed points. You can also open and use this demo as is in Clarion 5 as well.

Before you try the demo, make sure that you do indeed have a TCP/IP protocol stack on each machine that you intend to run the demo on. An easy way to test this is to use the PING command from the MS-DOS prompt to ping other machines on the network. The syntax of the command is PING ip-address. For example, type PING 127.0.0.1 if you want to ping your own machine, or put in another machine's address to check communication with it. If you receive replies, the stack is working properly; if not, you'll need to resolve these issues before the demo apps will run properly.

You must compile the application for 32-bit operation.

The demo is divided into two separate applications. I thought this would be a better way to show SocketWrench in action. The first application is the "Listener" called SWListen.app. This application opens a socket for listening. It accepts socket connections from other apps and responds to their commands. The second application is the "Controller" called SWCtrl.app. This application tries to connect to the "Listener" and tell it to do something.

In this example, the "Controller" can tell the "Listener" to beep a sound through its sound card, pop a message up on its screen, echo some text back to the "Controller", or launch another application on the "Listener's" PC. Finally, the "Controller" can also tell the "Listener" to shut itself down. Obviously, in real life, you could make either of the two applications perform whatever function you wanted.

Installation:

I would recommend that you download and try out the demo apps before you study the code too closely. Perform the following steps to install the demo:

  1. Unzip the entire archive into a single directory of your choice.
  2. Move or copy the SWRENCH.INC file into the LIBSRC directory under your CLARION5 directory. This step is optional, but recommended for any future apps you may develop.
  3. Move or copy the file CSWSK32.OCX into your Windows System directory, usually C:\WINDOWS\SYSTEM for Windows 95/98 or C:\WINNT\SYSTEM32 for Windows NT.
  4. Register the OCX by typing: REGSVR32 CSWSK32.OCX from the MS-DOS Command prompt. Be sure to type the command from within the appropriate system directory or the OCX will fail to register. Remember that the OCX needs to be registered on any PC that will run either of these apps.

Running Both Demo Apps on the Same PC:

  1. Launch C5, open SWListen.app, compile and run. Leave the application running. You should see a screen similar to the following:

Pic1.gif

  1. Note the IP address displayed, in this case 192.168.11.21
  2. Close SWListen.app. Open SWCtrl.app, compile and run. You should see a screen similar to the following:

Pic2.gif

  1. Enter the IP address of the "Listener" that you noted above. If you're running the "Listener" and the "Controller" on the same PC, both apps should display the same IP address.
  2. Push the Connect button to attempt a connection with the "Listener". If successful, the Connect button will change to Disconnect and you'll be able to choose a command from the drop down box.
  3. If the "Listener" PC has a sound card, select Beep, from the drop down combo box and push the Execute button. You should hear a sound and the two displays should look similar to the following:

Pic3.gif

Pic4.gif

  1. Now try some of the other options and see how they work. For the Echo, Message, and LaunchApp commands, you need to fill in the Text entry field with the appropriate message or application pathname. Try typing in an invalid command as well just to see what happens.

NOTE: If you choose a message, the message box will pop up over the "Listener" application. Be sure to clear it before you choose another command.

Implementation:

Now that you've seen it in action, let's take a look at the implementation. The SocketWrench documentation is actually pretty good. The first part includes an overall picture of Socket's programming and a quick demo of making a simple Echo application. Of course it's all in VB code and the Event Callback stuff is handled quite differently in Clarion. To be specific, although you can certainly query properties and kick off methods from inside the procedure you've designed, you don't have event notification there. Instead, it's in a callback function that's adjacent to your procedure. We need a way to get that event information back into your procedure where you can use it.

I've chosen to do this via user defined events. As you may know, you can define your own events as well as use the Clarion events in any program you write. The Clarion documentation recommends that your events should be numbered in the range 400 to FFF hex. I defined Clarion SocketWrench events in the 900 range that corresponded to each event the SW control can generate. I also translated a number of equates from VB as well. All of this is done in the file called SWRENCH.INC and helps to keep the SocketWrench documentation consistent with Clarion use.

The idea is that whenever a SocketWrench event callback occurs, a corresponding Clarion event is fired to handle it. Once you get past the callback business, it's Clarion coding as usual.

The primary embed points are in the OLE Event handler where the OCX posts its events, and ThisWindow.TakeEvent where they are actually processed. The example code is well documented so I won't cover any of that here.

You can communicate with the SocketWrench control two ways, and in Clarion you can use a combination of both in the same program. The most complete (and easiest in my opinion) at this time is by setting/reading various properties of the control and then processing any events that the control generates. You can also use the control's methods as well. The primary difference is that if an error occurs when using properties, an error event will be generated. If you use the methods, an error is returned by the method and no error event is generated. Although I don't follow this rule entirely, I do like having most of the errors generate an event, rather than check each method called individually.

Name Resolution:

Automatic name resolution (or lack thereof) can get you into trouble using the SocketWrench control. Most smaller LANs don't have a DNS server available to them and, even if they did, many times each individual host is not known to them. SocketWrench contains a property called 'AutoResolve' that determines whether it tries to resolve host names or not. If you give it a host name, it'll try to come up with an IP address for it and if you give it an IP address, it'll try to come up with a host name for it. If IP name resolution isn't in place, this can take several seconds to time out and cause your application to "hang" for a bit. If you know the IP addresses of the equipment you're working with and name resolution isn't part of your network, set this property to FALSE.

Complete name resolution on Microsoft TCP/IP networks can be a bit tricky at best, since Microsoft still wants to use NETBIOS over IP for name resolution. The SocketWrench control, on the other hand, doesn't know anything about NETBIOS (as it shouldn't), and may be unaware of various hosts on your network. This means that the host names that appear in Network Neighborhood for example, are generally resolved using NETBIOS broadcasts or a WINS server on the local subnet somewhere, and will not work as host names with SocketWrench.

It's easy to determine if you have standard IP name resolution in place on your network by using the PING command. You can use ping on names as well as IP addresses on a given network. If you issue PING ip-addr and all is well, but PING host-name fails, it will also fail with SocketWrench. You can fix this by implementing the DNS service on the server. Setting up DNS properly, however, can be another challenge by itself.

No discussion of name resolution would be complete without a short discourse on DHCP (Dynamic Host Configuration Protocol). DHCP is a service that can automatically assign IP addresses to hosts on the network. It does this via leases that generally expire after a period of time set by the network administrator. When the lease is half over, the host starts asking the DHCP server to renew its lease. If everything goes well, the host will continually have its lease renewed and the IP address will remain the same. However, if the lease actually expires, the IP address may be given to a new host. Your application will now be trying to talk to the wrong host and trouble could ensue. It's not a bad idea to have the remote host identify itself on the initial connect so that you can be sure you're talking to the right one.

The bottom line is that if name resolution is in place on your network, use it. It insulates you from any DHCP issues or just plain IP address re-assignment by the network administrator.

You can use the WINIPCFG program that comes with the IP stack on Win95/98 machines to verify if DHCP is active, when the lease was obtained and expires, if any name resolution (DNS or WINS) servers are available, and most anything else you can think relating to IP. If you're using NT, use the IPCONFIG /ALL command from an MS-DOS prompt. In our example, WINIPCFG displays the following:

Pic5.gif

Reading SocketWrench Properties:

Reading SW properties is very straightforward with one caveat. True/False properties work a little differently than in Clarion. In Clarion TRUE = 1, while FALSE = 0, but in VB, TRUE = -1 and FALSE= 0. When testing True/False properties, you can't use the TRUE equate, you must test for -1.

Reading Data from the Socket:

An important thing to keep in mind when sending data through the socket is that there really isn't any guarantee that it will get there. It is up to you to use some sort of acknowledgement scheme to ensure that the remote host actually received the data. Also, the data could get there in parts, generating multiple read events. The Read event is generated whenever there is data available to be read from the socket - it doesn't necessarily mean that all the data you sent has been received, however. On local area networks this rarely presents a problem since everything happens so fast, but on the Internet, latency and overhead are just a part of life.

You can approach this problem a couple of different ways. You can always make sure every packet is the same size, then use the 'RecvLen' property to verify that it's complete and send some sort of ACK/NACK back to the sending host. However, this is not appropriate for multi-step operations or when the data packets can not be the same size all of the time.

If you're sending text like we are in this example, you can also tell SW that no read is complete until it receives a CR/LF. To take advantage of this, you must set the 'Binary' property to FALSE and you must append a CR/LF to each piece of data that is sent. Look at the example code for additional details.

Parting Comments:

It's always great when a plan comes together and you can see the end of the tunnel. But sometimes you can really get bogged down in the implementation stage. It takes time to learn the ins and outs of a particular control and I think we can all agree that implementing these controls in Clarion hasn't always been very easy. It's not so much that Clarion doesn't support these controls adequately at this time, it's getting them working properly from inside Clarion that can be difficult. I think this is because most examples you see involve Visual Basic.

There is one tool mentioned in the reference manual that can really help in determining how the event callback thing is working for a given control. There is some sample code in the Callback Functions topic that shows each event being saved into a global queue. When I got started with SocketWrench, I got a basic echo server going and then monitored every event and every piece of data that event delivered by having it put into a global queue. I then had a browse procedure open with that queue displayed. Whenever any event involving the control occurred, it showed up in the queue and on my screen. You can use this information to enhance your understanding of the control and how it's performing in the Clarion environment.

Article comments

Post a comment

You must be logged on to post comments.

Clarion Roadmap

Try the roadmap (beta)

Search ClarionMag

 

Advanced search

From the archives

Superfiles and NAME

9/14/2009 12:00:00 AM

Having covered Superfiles in the previous episode, Steve Parker tackles the intricacies of how to set arbitrary names for the tables inside Superfiles.