TCP sockets in Pascal are generally hard to use; Free Pascal doesn't come with any high-level socket libraries by default, only a relatively low-level socket library. Some external libraries are available to make using sockets with Pascal easier, and one of these libraries is Synapse. Synapse is an easy-to-use socket library for Pascal, and in this blog post I'll try to show how to use Synapse to connect to a remote server and send/receive data from it.

From the official Synapse site:

This project deals with network communication by means of blocking (synchronous) sockets or with limited non-blocking mode. This project not using asynchronous sockets! The Project contains simple low level non-visual objects for easiest programming without problems. (no required multithread synchronisation, no need for windows message processing,…) Great for command line utilities, visual projects, NT services

"Installing" it

Firstly, you'll want to download the stable release of Synapse, and place them somewhere. At the time of writing, the latest Synapse version is release number 38. Once you've downloaded it, extract the files somewhere (it doesn't matter where you extract them to, as long as you remember the directory name. I'd suggest to create a directory for all your Free Pascal library code). Next, we need to edit the config file, so that Free Pascal can find these libraries. Open your Free Pascal configuration file (on Linux, this is at/etc/fpc.cfg. On Windows, this should be in the directory you installed Free Pascal to). Search for this:

# searchpath for libraries

Right before that, add -Fu followed by the path to the directory you made earlier. In my case, I added:
-Fu/home/daniel/fpc

Using it in your code

In most cases, you'll be using the TTCPBlockSocket class. This is included in the blcksock unit, so add this unit to the uses clause of your application:

uses blcksock;

Example

Connecting to a server

This is probably the most common way you'd use a socket — Connecting directly to another server. The functionality for this is contained in the TTCPBlockSocket class. Firstly, we need to define a variable to store the socket in:

var
	sock: TTCPBlockSocket;

And then we need to actually create the socket:
sock := TTCPBlockSocket.Create;

This creates a socket named sock that we're able to use. The next step is to connect to the remote server, using the Connect method:
sock.Connect('66.79.183.71', '80');
// Was there an error?
if sock.LastError <> 0 then
begin
	writeLn('Could not connect to server.');
	halt(1);
end;

At this point, the connection to the remote server has been established, and we may send and receive data.

Sending Data

Sending data is done via the SendString method. Note that this is slightly different to some other languages; it does not add a carriage return and linefeed to the end of the line, you have to add this manually if required.

sock.SendString('GET /blog/ HTTP/1.1'#13#10'Host: www.daniel15.com'#13#10#13#10);

Receiving Data

There are several methods for receiving data, but the two main ones are RecvString and RecvPacket. RecvString reads a single string (terminated by a carriage return and linefeed) from the socket, and returns this string without the carriage return. RecvPacket reads all data waiting to be read, and returns it unmodified (all carriage returns and linefeeds will still be there). Both commands take one parameter: A timeout. If the socket doesn't contain any data within this timeout, it returns a blank string.

buffer := sock.RecvPacket(2000);

Putting it all together

Here's an example application that connects to a web server, does a simple HTTP request, and writes the response to the console:

program TestApp;

uses
	blcksock;
	
var
	sock: TTCPBlockSocket;
	
procedure Main();
var
	buffer: String = '';
begin
	sock := TTCPBlockSocket.Create;
	
	sock.Connect('66.79.183.71', '80');
	// Was there an error?
	if sock.LastError <> 0 then
	begin
		writeLn('Could not connect to server.');
		halt(1);
	end;
	// Send a HTTP request
	sock.SendString('GET /blog/ HTTP/1.1'#13#10'Host: www.daniel15.com'#13#10#13#10);
	
	// Keep looping...
	repeat
		buffer := sock.RecvPacket(2000);
		write(buffer);
	// ...until there's no more data.
	until buffer = '';
end;


begin
	Main();
end.

The loop is needed because the data may come in multiple packets.

Not that this is not really a good example, as there's a HTTP library built-in to Synapse. The in-built HTTP library has several advantages, including the ability to use HTTP proxies. Perhaps I'll cover that in a future blog post :)

Tags tcp, sockets, pascal, winsock, hit1301, synapse

Short URL for sharing: https://d.sb/B15. This entry was posted on 21st March 2008 and is filed under pascal, HIT1301 Portfolio, Programming. You can leave a comment if you'd like to, or subscribe to the RSS feed to keep up-to-date with all my latest blog posts!

Comments

  1. Avatar for substance 01 substance 01 said:

    You have some great stuff on your blog. Your insight and expertise would be a welcome addition to our new community, i hope you will consider joining :-) and thanks for sharing!

  2. Avatar for SF SF said:

    Hi,

    thanks for the great work (synapse).

    How can I determine the local MAC - Adresse of my computer?

    1. Avatar for Daniel Lo Nigro Daniel Lo Nigro said:

      Not too sure, sorry.

  3. Avatar for Paul Paul said:

    Great example !

    Is there anything about a non-blocking example ?

    1. Avatar for Daniel Lo Nigro Daniel Lo Nigro said:

      I don't really use Pascal any more, so am not too sure how to use non-blocking sockets in it. Sorry :(

  4. Avatar for gee gee said:

    Great, great! Been looking for something like this with FreePascal all morning!

    Thank you!

    1. Avatar for Daniel Lo Nigro Daniel Lo Nigro said:

      No worries, glad it came in handy :)

  5. Avatar for vd vd said:

    Hi,

    above code is an eample of HTTP request, but is there any thing change when we do HTTPS request (on SSL enabled server)? I am getting error 302 Found when sending a request to SSL enabled server. Please give me some idea regarding this like how can I sort it out.
    Thanks.