DWise1's Sockets Programming Pages

General Structure of Network Applications




On the previous page, Working with Sockets, I covered the basic sockets functions and what each one does. Now on this page I describe the basic structure of network applications, demonstrate how those functions are used and how they work together, and link you to some sample applications that implement those basic network application structures. It is not enough to just know how to stuff the sockets API data structures and how to make the function calls; you also need to know how they are used in an actual application.

Client/Server Applications

Most network applications are of the client/server type. A client/server application actually consists of two separate applications usually, but not always, running on different computers:

There are a multitude of examples of client/server applications, including but not limited to:

Even in non-client/server applications (eg, peer-to-peer), because of the way that a network connection needs to be established, most network connections still end up following the basic client/server pattern:

I am unable to think of even a single network application that does not follow this pattern in some way. OK, maybe a broadcast server, but even then the client/server roles are simply reversed with the broadcast client application running a server socket that binds to a specific pre-determined port and "listens" for the broadcast server application; the mechanics of working the connection are the same, just reversed from the overall roles of the applications. Even the new peer-to-peer (P2P) networks require the nodes to be "listening" on specific ports in order to establish a connection.

Basic Client/Server Operation

Most networking applications involve one application waiting for a message from the other and then responding when it does receive a message. This situation presents itself very often and so needs to be studied and understood.

Basically, the server uses a specific, pre-determined port to wait for a client to contact it, whereupon the service is performed, the client ends the session, and the server goes back to waiting for a client to contact it.

The idea of the predetermined port is that the client needs to know what port the server is listening on in order to contact the server. As covered in the discussion of ports, the client would know what port to contact the server on by one of various means:

Let's designate the two ends of the connection as the "listener" and the "sender." Basically, the listener socket binds to a specific port and waits to receive a message, either with the listen() function (tcp) or with a recvfrom() (udp). The reason it has to bind to a specific port is because the sender must specify which remote port he is going to try to connect to, so the sender must know ahead of time which port that is going to be. This is why the well-known ports are used so much and why they are each reserved for a specific service. That way, your client can connect to the desired service on any server.

On the other hand, the sender does not need to bind to a specific port. When he connects to the listener, the OS automatically binds his socket to an unused port. Then that port number is included in the header of the packets he sends, so the listener is automatically told what port to send the response to. Nice and neat.

Client/Server Sequence of Communication

The following tables outline the basic sequence of actions performed by both parties in client/server communication. These differ depending on whether it's a TCP or a UDP connection. And although it's also a UDP application, I include the broadcast client/server as a separate example because it essentially represents a complete reversal of the roles of client and server.

The differences between the TCP and UDP protocols will come into play here, so you might want to review that topic at this point before continuing on.

Basic TCP Client/Server Sequence

Basically, in a client/server session using the TCP protocol, the client and server establish a connection over which they can pass several messages of virtually any size. The connection must be explicitly created (with the "Triple Handshake") and it must be explicitly shut down ("Shutting Down Gracefully"). By analogy, it's somewhat like a telephone conversation in which the connection is made, a series of messages are exchanged, and then the connection is closed.

Very basically, a TCP connection operates thus:

Here's what that sequence looks like in more detail:
Basic TCP Client/Server Sequence
1. Create a TCP socket with the socket() function.
2. Bind the socket to a specific port with the bind() function.
3.Call listen() to have that socket listen for a client trying to connect to it.
1. Create a TCP socket with the socket() function.
2. Connect to the server with the connect() function.
4. Accept the connection with the accept() function, which creates a client socket and starts the actual session.
3. Send (send()) the request.
5. Receive (recv()) the client's request.
6. Send (send()) a response.
4. Receive (recv()) the server's response.
7. Repeat the receive and send (Steps 5 & 6) as required. 5. Repeat the send and receive (Steps 3 & 4) as required.
6. Shut down (shutdown(1)) the connection.
8. When the client's shutdown action is detected, finish sending any remaining data and shut down (shutdown(1)) the connection.
7. When the server's shutdown action is detected, close the socket (close() or closesocket()) and exit.
9. Close the client socket (close() or closesocket()).
10. Continue Step 3. 8. Exit.
TCP Server Example (under construction) TCP Client Example (under construction)

Basic UDP Client/Server Sequence

Basically, in a client/server session using the UDP protocol, the client and server send individual datagrams to each other, all of which are limited in size. By analogy, it's like sending a letter: you send a single message (called a "datagram") and hope that it arrives at its destination intact.

Very basically, a UDP "connection" operates thus:

Here's what that sequence looks like in more detail:
Basic UDP Client/Server Sequence
1. Create a UDP socket with the socket() function.
2. Bind the socket to a specific port with the bind() function.
3. Wait to receive (recvfrom()) a message from a client.
1. Create a UDP socket with the socket() function.
2. Send (sendto()) the message to the server.
4. Receive (recvfrom()) the client's message.
5. Send (sendto()) a response, if required.
3. Receive (recvfrom()) the server's response.
6. Wait for the next message from a client (Step 3)
-- could be the same client or a different one.
4. Repeat the send and receive as required.
(each of which will be seen by the server as a separate communication)
5. Close the socket (close() or closesocket()).
6. Exit.
UDP Server Example (under construction) UDP Client Example (under construction)

Basic Broadcast Client/Server Sequence

A broadcast client/server application is a special kind of a UDP application. In this case, the roles are reversed in that it's now the client that waits to receive a message from the server. And instead of sending its datagram to only one host, the server uses a special broadcast address to send the datagram to every single host on the local network (routers are normally configured to block broadcasts, thus confining broadcasts to a single network segment).

There can also be applications where the broadcast server doesn't send an actual broadcast message, but instead works off of a kind of "subscriber list" of addresses to send the message to. In that case, the server would have to send the message not once but multiple times, once for every "subscriber". However, the server would also no longer be limited to just the local LAN segment, but could even send these messages out over the Internet. An example of this kind of a setup would be the list of trap addresses to be notified of events under Simple Network Management Protocol (SNMP).

Very basically, a broadcast client/server application operates thus:

Here's what that sequence looks like in more detail:

Basic Broadcast Client/Server Sequence
1. Create a UDP socket with the socket() function.
2. Bind the socket to a specific port with the bind() function.
3. Wait for a broadcast message on that port.
1. Create a UDP socket with the socket() function.
2. Broadcast the message (sendto()).
3. Close the socket (close() or closesocket()).
4. Receive (recvfrom()) and process the broadcast message. Send (sendto()) a response, if required.
4. Periodically repeat Steps 1 through 3. 5. Go back to step 3.
Broadcast Server Example (under construction) Broadcast Client Example (under construction)
Since the broadcast client/server is somewhat of a different beast than the previous two types, it may help to consider a few possible applications for you to see how it could be used. Remember that broadcasting is limited to a single LAN, since broadcast messages are normally blocked by routers.
  • Time Service
  • The time server periodically broadcasts its time and the clients use it to update their own time.

  • A "Who Has This?" Service
  • This is a simple discovery method. A user or program has requested a resource (eg, a particular file), so the server broadcasts a query asking everybody on the LAN who has that resource. The client that has that resource sends a datagram back to the server with enough information for the user/program to access that resource.

    Note that the Address Recognition Protocol (ARP) is an example of this application. Ethernet knows nothing about IP addresses, but rather can only address a host by its hardware address, AKA its "Media Access Control Address" (MAC address). TCP/IP applications use IP addresses and know nothing about MAC addresses. So when a host addresses a peer on the LAN by its IP address, ARP broadcasts a message asking "Who has this IP address?". Every host on the LAN receives the message and examines the IP address, but only the host that has that IP address responds with its MAC address. The requesting host then uses that MAC address to send its packet over Ethernet -- plus it saves that MAC address in its ARP cache for reuse in the immediate future, thus avoiding having to use ARP too often.

  • Request for a Service
  • Here, the names have been reversed back to normal order, but the operation is still the same. A client needs a service but does not know the address of the server nor even whether a server is present. So the client broadcasts its request and waits for a server to fulfill the request.

    A very common example of this is Dynamic Host Configuration Protocol (DHCP). A DHCP server has a pool of IP addresses that it dynamically leases out to hosts on the LAN. This pool of addresses normally only covers part of the range of addresses for that network segment; any devices, such as routers or printers, that require static addresses are assigned them outside the range of the dynamic address pools. A new host on a LAN starts out without an IP address, so it broadcasts a DHCP request, the DHCP server offers it an IP address, and the client accepts it. It is possible to have more than one DHCP server on a LAN (each managing different ranges of address) and so the client could receive more than one offer, but it will only accept one.

  • Roll Call / Poll
  • The server would broadcast a message requesting that all hosts on the LAN report back with certain information. That information could be host identification ("who's out there?"), host status/health, events/measurements recorded by the host, etc. As the hosts report back, the server would process the reports; eg, by logging the information in the network log, by detecting the loss of a host or addition of a new host (assuming the new host has this protocol running), by updating tables that match hosts with names, resources, or workloads, by detecting certain conditions that require it to respond by initiating certain processes.

    In Windows networking, something like this would be done to handle NetBIOS, wherein one or more hosts would be set up as "Master Browser". Part of a host's startup is to broadcast its name and server type (32 flags identifying whether it's a workstation, server, SQL server, time source, NT server, Windows 95+, domain or backup controller, master or backup or potential browser, print queue server, Novell, Apple, Xenix, OSF, VMS, wfw, etc), whereupon the Master Browser adds it to its tables. Then periodically thereafter (eg, 12 or 30 minutes), the host would again broadcast that information and the Master Browser updates its tables accordingly. If the host does not send its update on schedule, then the Master Browser removes it from its tables. Or the client could send a request (eg, local list or domain enumeration) to which the Master Browser will respond with the requested information.

    Another application comes to mind because of work I did in the late 1980's in the area of computerized greenhouse control. Since our application did not run TCP/IP nor Ethernet, the user had to manually add each sensor to the application database and then the application would periodically poll each sensor one at a time. If we had been able to set it up as a broadcast poll, then the application would have sent a single broadcast request for sensor readings and all of the sensors would respond (due to Ethernet collision detection and avoidance, only one would get through at a time, but eventually all would have gotten through).

    Return to Top of Page
    Return to DWise1's Sockets Programming Page
    Return to DWise1's Programming Page

    Contact me.

    Share and enjoy!

    First uploaded on 2007 January 06.
    Updated 2011 July 18.