Concepts / Writing a Simple Network Client

Writing a Simple Network Client

A server that finishes one client before accepting the next, as the DateServer sample does, can be held up by a single slow or idle connection.

  • Programming

One Slow Customer, Everyone Waits

Imagine a small shop with one counter and one clerk. The clerk serves a customer from start to finish before turning to the next person in line. If the first customer is quick, nobody minds. If the first customer settles in and talks for an hour, everyone behind them waits for that entire hour. A network server that handles connections one at a time has exactly this problem. This article looks at how a server can be structured so that one lingering client does not stop everyone else.

What do you think happens?

In the shop, the first customer talks for an hour. What happens to the customer standing behind them?

  • They are served right away at a second counter

  • They wait for the entire hour before being served

  • The clerk serves them in the middle of the first conversation

Reveal answer
Answer:

They wait for the entire hour before being served

The clerk handles one customer from start to finish before turning to the next person in line, so the customer behind the talkative one waits the whole time.

How a Non-Threaded Server Takes Turns

The DateServer.java sample program from this course is an extremely simple network server, and it does not use threads. Because of that, the server has to finish its work with one client before it can accept a connection from a different client. The server is not doing two jobs at once. It works through its connections in order.

The exchange with a client might be very brief, and for a simple date service it often is. Even so, we cannot assume every client will behave that way. A client could connect, stay connected for a long time, and keep the server occupied the whole while. In a server with no threads, every client that arrives during that time has to wait. The timeline below traces this for two clients.

Client 1 connectsserver accepts itServer serves Client1one path of executionClient 1 staysconnectedsends nothing usefulClient 2 waitsnot yet acceptedServer serves Client2only after Client 1finishesthenthenmeanwhileafter Client 1 is done
When the first client is slow or idle, what happens to the clients waiting behind it, and in what order do things happen over time?

Read the timeline from left to right. Client 2 has already tried to connect, but the server is still occupied with Client 1, so Client 2 cannot be served. The server is not slow at any single task; the problem is that there is only one line of work, and the first client controls how long that line stays busy.

Tracing an Idle Client Step by Step

The source names a specific problem case. A misbehaving client is one that stays connected without sending the data the server expects. This is not a client that sends bad data. It is a client that sends nothing useful while keeping the connection open. From the server's point of view, it is waiting for input that never arrives. The sequence below follows that situation in order.

Client Aconnected, sends nothingServersingle thread of workClient Btrying to connectconnectswaits for datasends nothingconnectsnot accepted yet
What does the server do step by step while a connected client sends nothing, and why can't the next client be accepted during that time?

The key point in the sequence is the server's single line of work. While the server is waiting on Client A for data that is not coming, it has no free capacity to deal with Client B. Client B's connection request exists, but the server, which finishes one client before accepting the next, cannot move on until Client A is handled.

Giving Each Connection Its Own Thread

A threaded server changes the ordering problem. Instead of one path of execution that must finish with each client in turn, the server uses threads so that it deals with several clients at the same time. A thread is an independent path of execution, so while one thread is waiting on one client, another thread can be working with a different client. The server is no longer locked to a single line.

Serverone program, severalthreadsThread 1its own path of executionThread 2its own path of executionClient Aone connectionClient Bone connectionstartsstartsservesserves
How do several client connections run at the same time when each one gets its own thread, and what stays shared versus separate between them?

The diagram shows only that several conversations can be in progress together, each on its own thread. It does not say the server is always fast, and it does not say threads are free. The benefit is that the progress of one client does not dictate when another client can be served. When Client A is slow or idle, Thread 2 can keep serving Client B.

Best practice

Converting a server to use threads changes the server's structure, but the client program can usually stay the same. The same techniques apply to more complicated servers, so the idea learned on a simple server carries over.

Comparing the Serial and Threaded Designs

It helps to set the two designs next to each other. The non-threaded server in the DateServer example works through its clients in sequence. The threaded server gives separate threads to separate connections. The table summarizes the differences that matter for the problem studied here.

QuestionSerial server (no threads)Threaded server (one thread per connection)
How clients are handledOne at a time, in orderSeveral at the same time, each on its own thread
Effect of an idle clientBlocks every client behind itTies up only its own thread; others continue
Waiting client's experienceWaits until the current client finishesServed while other threads are busy with other clients
Structure of the serverSingle path of executionSeveral paths of execution

Serial and threaded designs compared for the idle-client problem

When a Client Stays Silent

Watch what happens to the thread paired with a misbehaving client. That thread is waiting on a connection that is not producing the input it needs. In the source's words, this can hang up that thread indefinitely. The important point is what does not happen: the other threads keep going, and they can continue with other clients.

Working Through a Stalled Queue

MEDIUM

A serial server is handling Client 1, which connected and then sent nothing. Client 2 and Client 3 are both trying to connect. Explain what Client 2 and Client 3 experience, and then explain how the outcome would change if the server gave each connection its own thread.

Hints
  • Ask whether the server can accept Client 2 while it is still working with Client 1.
  • Consider which thread is affected when Client 1 stays silent, and whether the other threads can still serve Client 2 and Client 3.

Mistakes When Reasoning About Threads

  • Common mistake

    Thinking a silent client is a client that sends bad data

    What it looks like

    A client connects and sends nothing while keeping the connection open.

    Why it fails

    The source describes a misbehaving client as one that stays connected without sending the data the server expects. The problem is the absence of input, not corrupted input.

    Do this instead

    Describe the case as a connection that stays open without useful data.

  • Common mistake

    Assuming threads make each individual client faster

    What it looks like

    Expecting a single slow client to finish sooner just because the server has threads.

    Why it fails

    The source's point is that other clients need not wait; it does not claim each conversation becomes faster or that threads are free.

    Do this instead

    Credit threads with letting several clients progress together, not with speeding up any one of them.

  • Common mistake

    Believing the client program must be rewritten when the server gains threads

    Why it fails

    The source says converting the server changes its structure, and the client program can usually stay the same.

    Do this instead

    Focus structural changes on the server side.

  • Common mistake

    Assuming a non-threaded server can accept a new client while one is still connected

The source also notes that converting DateServer to use threads is not very useful in practice for such a simple server. DateServer's interaction with each client is short, so the benefit of threads hardly shows. The techniques matter most when individual interactions are long or unpredictable.

Key Takeaways

  • A server that finishes one client before accepting the next, as DateServer does, can be held up by a single slow or idle connection.
  • Threads are independent paths of execution, so a server with a thread per connection can serve several clients at the same time.
  • A client that stays connected without sending the expected data can hang up its own thread indefinitely, but other threads can keep serving other clients.
  • Converting a server to use threads changes the server's structure, while the client program can usually stay the same.