Introduction to Sockets

 

Introduction

Necessary Initialization Steps

Using the Network

Shutdown Steps

 

 

Introduction

An API (Application Program Interface) is a set of related functions. Usually APIs come with documentation and object code. This way one can write a program that makes the documented calls into the object code.

Sockets are an abstraction of network programming. They represent a duplex connection between two programs. That is, one can send & receive data using the same socket.

The Berkeley Sockets Interface is a standard API for using sockets of the IP Suite of protocols. This standard was invented about 20 years ago as part of the research for ARPA net. It defines about 12 functions. When we look at these functions you'll see how they are tied to IP suite of protocols.

The main benefit of using a standard API is that multiple implementations support it. The Berkeley Sockets Interface exists on most platforms that support the IP protocols. It is so common that I'll just refer to it as the sockets API. All the programming shown here was created and tested using MS-Windows Sockets. It should run on another platform with not much more than a recompile.

The socket functions allow one to create a socket, send data on the network, get data from the network, and destroy a socket. To get at these functions in the C programming language one must include a header file. On the MS-Windows implementation of sockets that header file is winsock.h, on most other implementations it is socket.h.

 

Necessary Initialization Steps

The first step is to initialize the socket's subsystem, like so:

// initialize winsock

WSADATA sd;

if(WSAStartup(MAKEWORD(1,1),&sd) != 0) {

// failure code ...

} else {

// success code ...

}

 

This just loads the file winsock.dll (on MS-Windows, in other implementations the file is probably different). The first parameter defines the version you intend to use. The convention is that the version number is made up of a major & minor version numbers and these numbers are put in the high & low order bytes of a word respectively. In the code the MAKEWORD macro does that for version 1.1.

 

 

The next step is creating a socket. Here is some code to do that. 

SOCKET s;

s = socket(AF_INET, SOCK_STREAM, 0);

if(s==INVALID_SOCKET)

{

// failure code ...

 

The SOCKET s is just a number that identifies the socket. AF_INET & SOCK_STREAM are both #defines from socket.h that describe the type of socket. AF_INET says it is an Internet socket (uses Address Family of the INET or IP addresses). SOCK_STREAM says it uses TCP on top of IP (connection oriented). For UDP use SOCK_DGRAM (for datagram).

 

 

The next step is to get the socket an address to connect on. There is a structure called a sockaddr_in (socket address) used for this. Here is some code that connects to a (probably) remote machine. This sample is hard-coded to go to the world wide web consortium's http server using IP.

sockaddr_in sa;

memset(&sa, 0, sizeof(sa));

 

// code to setup sa

sa.sin_addr.s_addr = inet_addr("18.23.0.23");

sa.sin_family = AF_INET;

sa.sin_port = 80;

There are 3 important data members of the sockaddr structure. The address family and address uniquely identify another machine. The actually identify another protocol stack, which could be on the same machine, but this is definitely not the ordinary case. The function inet_addr() is used to convert an address in "dot-form" into the binary form the sockaddr requires. This is probably a little used function, as there are several ways to get an internet address. The last member of note is the port. The port is used so that more than one process on 2 machines can communicate. There is a convention that certain ports will be used for certain application protocols. Port 80 is the standard for http. One can operate http on another port and this is common practice. However, to run something else on port 80 is considered against the convention. Similarly there are ports set aside for ftp, ping, gopher, ...

 

Using the Network

Now that we've initialized the sockets subsystem, created a socket and gotten an internet address it is time to communicate.

 

The next function, connect() is the one that attempts to find the other protocol stack. This is critical since it is the first function that will use the network. At home I use a modem to dial-up my ISP. The connect call is the first one we've seen that will initiate the phone call. Here is the call (pun intended):

if( connect(s, (struct sockaddr *) &sa, sizeof(sa)) == SOCKET_ERROR)

{

// failure code ...

Connect() attempts to find the other protocol stack. If it can't find the stack it will return SOCKET_ERROR (also defined in sockets.h). Also, connect identifies what we are doing as client programming. If we were writing a server we would listen for some other process to connect with us. Since we are the client we initiate the connection.

 

Once we have a connection we can send stuff over the network like so:

char szRequest[MAX_MESSAGE_LENGTH];

memset(szRequest, 0, MAX_MESSAGE_LENGTH);

sprintf(szRequest, "GET /pub/WWW/ HTTP/1.0\r\n\r\n");

 

if(SOCKET_ERROR == send(s, szRequest, strlen(szRequest), 0))

{

// failure code ...

Give send the socket, a string, the strings length, simple. The fourth parameter is a flag.

 

 

Shutdown Steps

When you are done sending data on your socket, there are a few closing steps:

closesocket(s);

WSACleanup();

 

That's it. Now you are ready to move on to the example that puts it all together with the http protocol.

 

 

Back to Contents