Showing posts with label Multi-Threading. Show all posts
Showing posts with label Multi-Threading. Show all posts

Sunday, January 6, 2013

Multi-Threaded Socket Programming in Java (Part II- Client)

As you saw in first part of Multi-Threader Socket Programming, we handled everything from the server's point of view. There are not so much thing going on at the client's side, and technically speaking you should bear in mind that client will not even know how the server processes its request. So the client part's code is not really dependent toward the context of threading obviously.
        
        Socket socket = null;
        PrintWriter out = null;
        BufferedReader in = null;

        try {
            socket = new Socket("Amir", 8081);
            out = new PrintWriter(socket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        } catch (UnknownHostException e) {
            System.err.println("Don't know about host: Amir.");
            System.exit(1);
        } catch (IOException e) {
            System.err.println("Couldn't get I/O for the connection to: Amir.");
            System.exit(1);
        }

As you can see, we initiated the socket with the Server Socket's name and port. The PrintWriter is getting the output stream of the socket so that we can later write on it and we also initialized an BufferedReader object to receive the stream of server's response.
        
        String serverMessage;
        while ((serverMessage = in.readLine()) != null) {
            System.out.println("Server: " + serverMessage);
            if (serverMessage.contains("MESSAGE RECEIVED"))
                break;
        }  

As you can see, listening for server's response and if the Server's response contains the String literal "MESSAGE RECEIVED", the loop is broken. This part is inside my very own protocol, and you can have whatever you would like to have there. Finally, you just have to remember to close the streams and sockets in order to avoid any resource leaks:

        out.close();
        in.close();
        socket.close();

So we are done. I tried to come up with something very easy and therefore you do not get lost in there. However, if anyone is interested in having a whole sort of real application up and running, take a look at the Source repository here: https://github.com/fidelio-coder/MultiThreadServer 

Monday, December 31, 2012

Multi-threaded Socket Programming in Java (Part I - Server-Side)


The idea behind this post to create a minimalist Client/Server application that can be run within a network. There are many valuable posts about the same topic, but most of them tend to be long and it is hard to get the actual meat in a rather shorter time.

Let's first briefly go over some network programming buzzwords:

  • Port: Type of software constructor which is used as a communication endpoint at Server-Side. Ports are either process-specific or application-specific and are mainly used in Transport Layer protocols such as TCP/IP. 
  • Socket : one end-point of a two-way communication link between two programs running on the network. A socket is bound to a specific port number.

Single-Threaded Server:

In the below code, what you need to do is to simply Create a ServerSocket object with the port number. Afterwards, the server instance listens on a port for a connection request from a client and accepts it right after that. Notice that the reason it is a single-thread server processor is that if two clients request for a connection at the same-time, the second client will not be processed unless the server is done with the first client's request.


import java.io.IOException;
import java.net.ServerSocket;
public class Server {

    public static void main(String[] args) throws IOException {

        ServerSocket serverSocket = null;

    try {
        serverSocket = new ServerSocket(8081);
    }
    catch (IOException e){
            System.out.println("Could not listen on port 8081!");
            System.exit(-1);
        }
    
    Socket clientSocket = null;
    try {
        clientSocket = serverSocket.accept();
    } 
    catch (IOException e) {
        System.out.println("Accept failed: 8081");
        System.exit(-1);
    }
  }
}

Multi-threaded Server

As I said earlier, the single-threaded server is not gonna work is almost all cases. With all of computers having dual/triple core servers, a programmer needs to be able to use that opportunity to deliver faster solutions. Java makes concurrent programming really easy by the abstraction layers it has created inside the language libraries.

Let us start with the simplest situation possible. In the multi-threaded case, server will listen to a client request and as soon as it gets the request, starts a Thread and process it. For that, we need to replace the following lines:


Socket clientSocket = null;
    try {
        clientSocket = serverSocket.accept();
    }

With this:

while (true)
    {
        new MultiServerThread(serverSocket.accept()).start();
    }


In here, the MultiServerThread class will handle most of the Server's work. This class will inherent Thread as its super class. As you may know, while implementing Thread, you will do most of your work in the run method as below:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class MultiServerThread extends Thread {

    Socket socket;

    public MultiServerThread(Socket socket) {
        super("MultiServerThread");
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            BufferedReader in = new BufferedReader(
                                    new InputStreamReader(
                                            socket.getInputStream()));
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            //Implement Server Protocol and Methods in Here
            }

            out.close();
            in.close();
            socket.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

As you can see in the code, you can instantiate Bufferedreader to read the Client's request and process that later. Also, you need to instantiate PrintWriter object with the OutputStream of the Socket to write the message back to client. Note that you should close the Streams as it can exploit your program to a Memory leak.

The second part of this entry can be found here: Multi-Threaded Socket Programming in Java (Part II- Client)