Implementing a Remote Com Port

APRO makes it easy to make a serial port accessible to other machines across your network.  By using the TApdWinsockPort and TApdComPort components in conjunction, a port on your PC, and the device that is attached to it, can be controlled by another machine.

The actual process of doing this is very simple.  The output of the COM port is redirected to the input of a Winsock port and the output of the Winsock port is used as the input for the COM port.

Example: Redirecting a Single Port

Drop a TApdWinsockPort component on a form.  Set the DeviceLayer property to dlWinsock.  Set the WsMode property to wsServer.  Set the WsAddress property to the IP address of the machine you are redirecting.  Any unused port can be used for the WsPort property.  The default telnet port works well for this.  However, if multiple ports are going to be redirected on one machine, this property becomes more important.

Then drop a TApdComPort component on the form.  Set the properties to reflect the port that you want to redirect.  The ComNumber property should be set to a value other than zero.

Finally, you will want to redirect the output of the COM port to the Winsock port and vice versa.  This is done by assigning OnTriggerAvail events for both components.

In Delphi, the code for this looks like this:

procedure TForm1.ApdComPort1TriggerAvail(CP: TObject; Count: Word);

var

  i : Integer;

begin

  for i := 1 to Count do

    ApdWinsockPort1.PutChar (ApdComPort1.GetChar);

end;

procedure TForm1.ApdWinsockPort1TriggerAvail(CP: TObject; Count: Word);

var

  i : Integer;

begin

  for i := 1 to Count do

    ApdComPort1.PutChar (ApdWinsockPort1.GetChar);

end;

In C++ Builder:

//-------------------------------------------------------------

 

void __fastcall TForm1::ApdComPort1TriggerAvail (

    TObject *CP,

    WORD Count)

{

  for (int i = 0; i < Count; i++)

    ApdWinsockPort1->PutChar (ApdComPort1->GetChar ());

}

//-------------------------------------------------------------

 

void __fastcall Tform1::ApdWinsockPort1TriggerAvail(

    TObject *CP,

    WORD Count)

{

  for (int i = 0; i < Count; i++)

    ApdComPort1->PutChar (ApdWinsockPort1->GetChar ());

}

//-------------------------------------------------------------

To use the newly created remote serial port, in a separate application drop a ApdWinsockPort on form.  Set the WsMode property to wsClient.  Set the WsAddress property to the IP address of the machine you are redirecting (specified above).  The WsPort property should be set to the same port specified by the redirector software.

Run the redirector software on the machine containing the port you want to redirect.  Then run the client software on the remote PC.  You should be able to connect to the remote port.  For testing purposes, a TAdTerminal connected to the TApdWinsockPort component in both the redirector software and the remote software can be a helpful aid in testing.

Redirecting Multiple Ports on one Machine

The process of redirecting multiple ports on one machine is similar to a single COM port.  The main difference is that the TApdWinsockPort component only supports one connection at a time.  To get around this, use a block of Winsock ports for each of the COM ports you are redirecting.  For example, if you are redirecting COM1-COM4, you could assign the ports to TApdWinsockPorts 5001 – 5004 respectively.  Thus, to access COM2 on the remote machine, you would connect to WsPort 5002 of the Winsock port.

The trickiest part of this is making sure that you keep the ports straight.  Port 1 redirects to Winsock port 1 and vice versa.  The code for each port looks similar enough that it can be hard to spot misredirections.

Sharing a Com Port

The technique of using multiple TApdWinsockPorts assigned to multiple ports can be used to share a single COM port amongst multiple applications.  The modification needed to do this is to redirect the output of the serial port to all the Winsock ports.  The Winsock ports will continue to redirect their output to the COM part as normal. 

The remotes applications do not need to run on a remote machine; they can be ran on the local machine.  This trick can be used to share a COM port to multiple applications on one machine or multiple applications on multiple machines.

Here is a Delphi example for this:

procedure TForm1.ApdComPort1TriggerAvail(CP: TObject; Count: Word);

var

  i : Integer;

  c : Char;

begin

  for i := 1 to Count do begin

    c := ApdComPort1.GetChar;

    ApdWinsockPort1.PutChar (c);

    ApdWinsockPort2.PutChar (c);

    ApdWinsockPort3.PutChar (c);

  end;

end;

procedure TForm1.ApdWinsockPort1TriggerAvail(CP: TObject; Count: Word);

var

  i : Integer;

begin

  for i := 1 to Count do

    ApdComPort1.PutChar (ApdWinsockPort1.GetChar);

end;

procedure TForm1.ApdWinsockPort2TriggerAvail(CP: TObject; Count: Word);

var

  i : Integer;

begin

  for i := 1 to Count do

    ApdComPort1.PutChar (ApdWinsockPort2.GetChar);

end;

procedure TForm1.ApdWinsockPort3TriggerAvail(CP: TObject; Count: Word);

var

  i : Integer;

begin

  for i := 1 to Count do

    ApdComPort1.PutChar (ApdWinsockPort3.GetChar);

end;

C++ Builder:

//-------------------------------------------------------------

void __fastcall TForm1::ApdComPort1TriggerAvail(TObject *CP, WORD Count)

{

  char c;

  for (int i = 0; i < Count; i++) {

    c = ApdComPort1->GetChar();

    ApdWinsockPort1->PutChar (c);

    ApdWinsockPort2->PutChar (c);

    ApdWinsockPort3->PutChar (c);

  }

}

//-------------------------------------------------------------

void __fastcall TForm1::ApdWinsockPort1TriggerAvail(TObject *CP,

      WORD Count)

{

  for (int i = 0; i < Count; i++)

    ApdComPort1->PutChar (ApdWinsockPort1->GetChar());

}

//-------------------------------------------------------------

void __fastcall Tform1::ApdWinsockPort2TriggerAvail(

    TObject *CP,

    WORD Count)

{

  for (int i = 0; i < Count; i++)

    ApdComPort1->PutChar (ApdWinsockPort2->GetChar());

}

//-------------------------------------------------------------

void __fastcall Tform1::ApdWinsockPort3TriggerAvail(

    TObject *CP,

    WORD Count)

{

  for (int i = 0; i < Count; i++)

    ApdComPort1->PutChar (ApdWinsockPort3->GetChar());

}

//-------------------------------------------------------------

Getting this all to work can be a bit trickier than it looks.  Chances are you will be dealing with numerous ports.  It is easy to get things mixed up.  During the testing phase, I would strongly recommend attaching a terminal to each port, so that you can see where the data is going.

The above example shows sharing a remote port to three TApdWinsockPorts dropped on a form.  You can add more flexibility by creating the TApdWinsockPort components dynamically.  In this case, you would want a TApdWinsockPort with a known port address to control the creation and deletion of the new TApdWinsockPorts. 

For example, let’s say that the known TApdWinsockPort is on port 5000.  The client application would connect on port 5000 and request a port.  The server application would send back the next available port (5001 in this example).  The client would disconnect from port 5000, the server would create a new TApdWinsockPort component dynamically using port 5001 and the client application would connect to port 5001. 

The next client would then connect to port 5000 and request a port.  The server would respond with 5002, create the port and the client would connect to that one.

When a client was finished with a port, it would send an “I am done with port xxxx” message and disconnect.  The server, on receipt of this message, would close and destroy the TApdWinsockPort connected to the port specified by the client.

Another tricky aspect for dealing with sharing a COM port amongst multiple applications has to do with the applications attempting to control the port at the same time.  If you do not implement some sort of management, you can get some very tangled data going through the COM port. 

The easiest way to handle it is to assign two TApdWinsockPorts for each client.  One port (the data port) will just send data back and forth between the ports as shown in the above example.  The other port (the control port) would be used to request access to the port.  If the port is available, the server program would then assign the OnTriggerAvail event of the appropriate server side to redirect to the COM port until the client application releases the port.  While one client has the port, the other applications would not be able to access it.

The messages sent through the control port can be expanded to include such things as is the port busy, which client is using the port, and turning on/off passively listening to data coming in the COM port.

Closing Thoughts

Using this technique is not just limited to the TApdWinsockPort.  If you have iPRO, you can use the TIpServer and TIpClient component in place of the TApdWinsockPort.  There are advantages to doing this.  The iPRO components are more sophisticated in their handling of Winsock.  The iPRO components allow multiple simultaneous connections.  In dealing with multiple clients to a single port (or even multiple ports to a single client), this additional functionality can be very useful.

 

This site is not affiliated, endorsed, or otherwise associated with the entity formerly known as TurboPower Software. The owners and maintainers of Aprozilla.com were merely meager employees of the aforementioned organization, providing this site out of the pure goodness of their collective hearts. SourceForge.net Logo

Last updated: July 22, 2003.