Making a connection — Chapter 15

Upulie Handalage
6 min readJul 25, 2022

488–545

Your Java program should be able to connect with another program in order make a proper system. Java takes care of all the low-level networking details through the java.net library. Java’s biggest benefits is its ability to send and receive data over either a file or network with a simple connection stream, using a class like BufferedReader. This chapter will talk about sockets, including client-sockets and server-sockets which could be then turned into clients and servers that talk with each other, in a multithreaded manner)

There are three things we have to learn to get the client working

  1. How to establish the initial connection between the client and server
  2. How to send messages from the client
  3. How to receive messages from the server

To make a socket connection, you need to know 2 things about the server:

  1. who it is (IP address)
  2. which port its running on (TCP port)

TCP ports

The TCP port numbers range from 0 to 1023 — are reserved for well known services. Don’t use them for your own server programs.

Few more import points from the chapter

  1. Client and server applications communicate over a Socket connection.
  2. A Socket represents a connection between two applications which may (or may not) be running on two different physical machines.
  3. A client must know the IP address (or domain name) and the tcp port number of the server application.
  4. A tcp port is a 16-bit unsigned number assigned to a specific server application. TCP port numbers allow different clients to connect to the same machine but communicate with different applications running on that machine.
  5. The port numbers from 0 through 1023 are reserved for well-known services including HTTP, FTP, SMTP, etc.
  6. A client connects to a server by making a Server socket

Socket s= new Socket(“127.0.0.1”, 4200);

7. Once connected, a client can get input and output streams from the socket. These are low-level connection’ streams.

sock.getInputstream();

8. To read text data from the server, create a BufferedReader, chained to an InputStreamReader. which is chained to the input stream from the Socket.

9. InputStreamReader is a bridge stream that takes in bytes and converts them to text (character) data. Its used primarily to act as the middle chain between the high-level BufferedReader and the low-level Socket input stream.

10. To write text data to the server, create a PrintWriter chained directly to the Socket’s output stream. Call the print or println() methods to send Strings to the server.

11. Servers use a ServerSocket that waits for client requests on a particular port number.

12. When a ServerSocket gets a request it accepts the request by making a Socket connection with the client.

Threads

A thread is a separate thread of execution (a separate call slack) It is a Java class that represents a thread.

How to launch a new thread

  1. Make a Runnable object

Runnable threadJob = new MyRunnable();

Runnable is an interface

2. Make a Thread object (the worker) and give it a Runnable (the job)

Thread myThread = new Thread(threadJob);

Pass the new Runnable object to the Thread constructor. This tells the new Thread object which method to put on the bottom of the new stack-the Runnable’s run() method.

3. Start the Thread

myThread.start();

Nothing happens until you call the Thread’s start() method. That’s when you go from having just a Thread instance to having a new thread of execution. When the new thread starts up. it takes the Runnable object’s run() method and puts it on the bottom of the new thread’s stack.

Runnable

Runnable is to a Thread what a job is to a worker. A Runnable is the job a thread is supposed to run. A Runnable holds the method that goes on the bottom of the new thread’s stack (run()). Once the thread becomes runnable, it can move back and forth between runnable, running, and an additional state: temporarily not runnable (also known as ‘blocked’).

The Thread Scheduler

It makes all the decisions about who moves from runnable to running. And about when (and under what circumstances) a thread leaves the running state. The scheduler decides who runs, and for how long, and where the threads go when the scheduler decides to kick them out of the currently running state.

Few more points about threads

  1. A thread with a lower-case “t” is a separate thread of execution in Java.
  2. Every thread In Java has its own call stack.
  3. A Thread with a capital “T” is the java.lang.Thread class. A Thread object represents a thread of execution.
  4. A Thread needs a job to do. A Thread’s job is an instance of something that implements the Runnable interface.
  5. The Runnable interface has just a single method, run(). This is the method that goes on the bottom of the new call stack. In other words. it is the first method to run in the new thread.
  6. To launch a new thread, you need a Runnable to pass to the Thread’s constructor.
  7. A thread is in the NEW state when you have instantiated a Thread object but have not yet called start().
  8. When you start a thread (by calling the Thread object’s start() method), a new stack is created, with the Runnable’s run() method on the bottom of the stack. The thread is now in the RUNNABLE state, waiting to be chosen to run.
  9. A thread is said to be RUNNING when the JVM’s thread scheduler has selected it to be the currently running thread. On a single-processor machine, there can be only one currently-running thread.
  10. Sometimes a thread can be moved from the RUNNING state to a BLOCKED (temporarily non-runnable) state. A thread might be blocked because it’s waiting for data from a stream. Or because it has gone to sleep, or because it is waiting for an object’s lock.
  11. Thread scheduling is not guaranteed to work in any particular way, so you cannot be certain that threads will take turns nicely. You can help influence turn taking by putting your threads to sleep periodically.

try {

Thread.sleep(2000) ;

}catch(InterruptedException ex){

ex.printStackTrace();

}

12. Threads can lead to concurrent issues; which can be omitted by using a lock based implementation for resources. Every Java object has a lock. A lock has only one key. Most of the time, the lock is unlocked and nobody cares. But if an object has synchronized methods, a thread can enter one of the synchronized methods only if another thread hasn’t already grabbed the one key. However, having synchronized methods could also lead to deadlocks.

Few more things about threads

  1. The static Thread.sleep() method forces a thread to leave the running state for atleast the duration passed to the sleep method. Thread.sleep(200) //puts a thread to sleep for 200 milliseconds.
  2. The sleep() method throws a checked exception (InterruptedException), so all calls to sleep must be wrapped in a try/catch. or declared.
  3. You can use sleep() to help make sure all threads get a chance to run, although there’s no guarantee that when a thread wakes up it’ll go to the end of the runnable line. It might for example, go right back to the front. In most cases, appropriately-timed sleep() calls are all you need to keep your threads Switching nicely.
  4. You can name a thread using the (yet another surprise) setNameO method. All threads get a default name, but giving them an explicit name can help you keep track of threads. especially if you’re debugging with print statements.
  5. You can have serious problems with threads if two or more threads have access to the same object on the heap.
  6. Two or more threads accessing the same object can lead to data corruption if one thread, for example, leaves the running state while still in the middle of manipulating an object’s critical state. • To make your objects thread-safe, decide which statements should be treated as one atomic process (before another thread enters the same method on the same object)
  7. Use the keyword synchronized to modify a method declaration, when you want to prevent two threads from entering that method.
  8. Every object has a single lock, with a single key for that lock. Most of the time we don’t care about that lock; locks come into play only when an object has synchronized methods.
  9. When a thread attempts to enter a synchronized method, the thread must get the key for that object, if it is not available, the thread goes into a kind of waiting lounge. until the key becomes available.
  10. Even if an object has more than one synchronized method, there is still only one key. Once any thread has entered asynchronized method on that object, no thread can enter any other synchronized method on the same object This restriction lets you protect your data by synchronizing any method that manipulates the data.

--

--

Upulie Handalage

Everything in my point of view. Here for you to read on....