Saturday, 23 January 2016

ECHO SERVER

  Echo server is a simple server with only one job to send back whatever is sent to it.

  This post is about creating a simple Echo server on your local machine using JAVA programming language.


STEPS INVOLVED

  

Step 1 : create a socket for the echo server.

Step 2 : take ip address and port number as inputs from the user.

Step 3 : bind the ip address and the port number to the echo server socket created in step 1.

Step 4 : wait for the client's request.

Step 5 : once the client is connected to the echo server, assign it an independent thread for further execution.
[Note : Each client will be assigned a different independent thread]

Step 6 : the work of each thread is to simply send back the information received from the client.


PROGRAM :-


Programs are quite self explanatory as comments are added when and where necessary.

First is the Echo Server program that actually creates the echo server for the clients to connect.

Second is an optional program to connect to Echo Server.
If you are familiar with telnet or similar applications, you can connect to echo server using them and skip the Client program provided.

[Note : Program seems to be in plain text here, I am working on it. Till then copy it to your editor so that keywords are highlighted]
 

1. Echo Server Program 

import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.util.Scanner;

public class EchoServer {

    public static void main(String args[]){
   
        try{
   
            // echo server socket
            ServerSocket serverSocket;
   
            // total number of clients
            int clientCount = 0;
       
            // echo server socket address
            SocketAddress serverSocketAddress;
   
            // to obtain input from standard input i.e. keyboard
            Scanner scanner = new Scanner(System.in);
   
            // getting socket address from user  to create echo server socket
            System.out.println("Socket Address :- \n");
           
            System.out.print("\tIP Address :\t");
            String serverIP = scanner.next();
       
            System.out.print("\tPort number :\t");
            short serverPort = Short.parseShort(scanner.next());
       
            serverSocketAddress = new InetSocketAddress(InetAddress.getByName(serverIP), serverPort);
   
            // creation & binding of echo server socket
       
            // echo server socket creation
            serverSocket = new ServerSocket();
       
            // echo server binding
            serverSocket.bind(serverSocketAddress);
       
            if (serverSocket.isBound()){
                System.out.println("Echo Server successfully bound to : " + serverSocketAddress);
            }
            else{
                System.out.println("Echo Server binding unsuccessful");
                System.exit(0);
            }
       
            while (true){
       
                // listening and then accepting client's request to connect
                Socket clientSocket = serverSocket.accept();
               
                if (clientSocket.isConnected()){
                    System.out.println("\nConnected to "+clientSocket.getInetAddress() + '\n');
                    clientCount++;
           
                    // client count as thread name
                    String threadName = Integer.toString(clientCount);
                   
                    Clients client = new Clients(threadName, clientSocket);                   
                }
            }
        }catch(Exception e){
            System.out.println("Exception : " + e.getMessage());
        }
    }
}

class Clients implements Runnable{
   
    // client thread
    private Thread clientThread;
   
    // client socket to communicate
    private Socket clientSocket;
   
    // constructor to initialize the constructor class
    Clients(String clientId,  Socket clientSocket){
       
        // thread name as client id
        clientThread = new Thread(this, clientId);

        this.clientSocket = clientSocket;
       
        // calls the run method
        clientThread.start();
    }
   
    public void run(){
   
        // Scanner object to read data from the standard input
        Scanner scanner = new Scanner(System.in);
   
        // TODO : for the time being only one msg
        try{
            while (true){
               
                // to map the received bytes from client to characters
                InputStreamReader inputStreamReader = new InputStreamReader(clientSocket.getInputStream());
               
                // to store charset mapped received data
                char[] recvData = new char[100];

                // reading data from the input stream
                inputStreamReader.read(recvData, 0, recvData.length);
                System.out.println("Client "+clientThread.getName()+ " : " + new String(recvData));
       
                // sending data to the client
                clientSocket.getOutputStream().write(new String(recvData).getBytes());
            }   
        } catch(Exception e){
                System.out.println("Exception : " + e.getMessage());
        }
    }
}


2. Client Program


import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;

public class Client{
   
    public static void main(String args[]){
   
        // object of Scanner class to handle standard input
        Scanner scanner = new Scanner(System.in);
       
        // server socket to communicate with the server
        Socket serverSocket;
   
        try{
            // getting server socket address from the user to connect
            System.out.println("Server Socket Address :- \n");
           
            System.out.print("\tIP Address :\t");
            String serverIP = scanner.next();
           
            System.out.print("\tPort number :\t");
            short serverPort = Short.parseShort(scanner.next());
           
            // connecting to the specified server
            serverSocket = new Socket(InetAddress.getByName(serverIP), serverPort);
            if (serverSocket.isConnected()){
                System.out.println("\nConnected to "+ serverSocket.getInetAddress() + "\n");
            } else{
                System.out.println("\nConnection FAILED ");
                return;
            }
           
            while (true){
           
                // data to send to the Echo Server
                String dataToSend="";
               
                // to store charset mapped received data
                char[] recvData = new char[100];
               
                // to map the received bytes from the echo server to characters
                InputStreamReader reader = new InputStreamReader(serverSocket.getInputStream());
           
                System.out.print("Me : ");
                // nextLine() must read my input and not the pre existing \n in buffer
                while(dataToSend.length()==0)
                     dataToSend = scanner.nextLine();
           
                // sending data to the server
                serverSocket.getOutputStream().write(dataToSend.getBytes());
           
                // receiving data from the server
                reader.read(recvData, 0, recvData.length);
                System.out.println("Server : " + new String(recvData));
                           
                System.out.println();
            }
        }catch(Exception e){
            System.out.println(e.getMessage());
        }
    }
}


HOW TO RUN THE PROGRAM? 

 

First Echo Server program must be executed
  • Compile and run the Echo Server Program.
  • Enter the ip address assigned to your PC (type 127.0.0.1 if client program is also executed from the same machine).
  • Enter any valid non-reserved port number.
  • Echo Server is created. Now the program will wait for the clients to connect.

Once Echo Server is created, execute the client program

  • Compile and run the Client Program. 
  • Enter the ip address and the port number of the echo server when prompted.
  • Now you will be connected to the echo server.
  • Whatever you send will be echoed back by the Echo Server.  

OUTPUT 


Output from the client's side :-


Client 1 :



Client 2 :



 Output from the echo server's side :-




This is a basic program which can become a foundation for the advanced program that you are going to make ;)

Tuesday, 18 August 2015

CHANGING GRUB2 BACKGROUND IMAGE


      Tired of looking at the same purple background image of GRUB2? Well, now is the time to change it and have a background image of your own.

This is a pretty simple operation completed in few steps as listed below :-


Step 1 : Open the terminal(Ctrl+Alt+t) and then open the file '/etc/default/grub' with superuser privileges by typing the following command :
     
                            sudo gedit /etc/default/grub

This file defines the settings for GRUB2.
 

Step 2 :  Add a line to the file :

                        GRUB_BACKGROUND="<full path of your image>"

(Note : I believe that there are certain specifications that an image must pass in order to qualify for the grub background image. So don't loose hope if your image is not set as grub background image, just try another image with different specifications).


Step 3 : These changes are not reflected into the GRUB2 until the following command is run:

                         sudo update-grub

The file that configures GRUB2 is grub.cfg which inherits settings from the grub file we have been making changes to. So this command replaces the old grub.cfg file with new grub.cfg file with the settings we just defined in grub file.


      

   Now every time I start my laptop, I can look at a cool image of my choice. What do you want to see?

Monday, 3 August 2015

BOOT INTO GRUB BY DEFAULT

      Earlier, life was so simple. After Ubuntu installation GRUB was booted by default as soon as the PC was turned on. From there, the user was able to select the OS of his choice - be it Windows or Ubuntu.

     But nowadays I find many PCs(mostly HP) that are hard coded to boot from Microsoft's boot loader. As a result of which, even after installing Ubuntu, the PC directly boots into Windows by default without giving the user a choice to boot into Ubuntu.

     The only way to load GRUB is to press f9 as soon as the PC starts and then choose Ubuntu. This is so not cool. Here are quick steps which will make your PC to BOOT INTO GRUB BY DEFAULT. 

QUICK STEPS

 

Step 1: Firstly, boot into Ubuntu using the key used to change the boot options.(ex: f9 for hp, f12 for Dell)

Step 2: Open the terminal(Ctrl+Alt+t) and type the command: 

sudo su

And enter the password when prompted for it.

Step 3: Make a backup of the boot directory(/boot) by copying and saving it onto the hdd by typing the following command:

cp -r /boot boot.bkp

(Note : This command will create a backup of the boot directory as boot.bkp on the current working directory.)
 
Step 4:  Now move the file /boot/efi/EFI/Microsoft/Boot/bootmgfw.efi to the path /boot/efi/EFI/Microsoft by typing in the following command:

mv /boot/efi/EFI/Microsoft/Boot/bootmgfw.efi /boot/efi/EFI/Microsoft


(Note : If you don't find this file in the location mentioned in the command, refer to the reason given for this step below in the blog.)

Step 5: Copy the files grubx64.efi and shimx64.efi from /boot/efi/EFI/Ubuntu and paste it into /boot/efi/EFI/Microsoft/Boot folder by typing the following command:

cp /boot/efi/EFI/Ubuntu/grubx64.efi /boot/efi/EFI/Ubuntu/shimx64.efi /boot/efi/EFI/Microsoft/Boot

Step 6: Rename the file shimx64.efi to bootmgfw.efi by typing the following command:

mv /boot/efi/EFI/Microsoft/Boot/shimx64.efi /boot/efi/EFI/Microsoft/Boot/bootmgfw.efi

Step 7: Now open the file /boot/grub/grub.cfg in gedit by typing the following command:

gedit /boot/grub/grub.cfg

Find(Ctrl+f) "chainloader" in the file.

(Note : You will be directed to the line: "chainloader /EFI/Microsoft/Boot/bootmgfw.efi".)

Step 8: Edit that line to "chainloader /EFI/Microsoft/bootmgfw.efi" and save the changes.


After following these steps, when you turn on your PC the next time, you will be shown GRUB by default from where you can choose the OS of your choice.


WHY THESE STEPS? 

 


          The reason why these certain PC's boot into Windows by default is because the boot order of Microsoft's boot loader is set first in the list.
So when PC is turned ON, the Microsoft's boot loader(bootmgfw.efi) boots and Windows is loaded.

By executing these steps, we are fooling the PC to boot GRUB(by loading shimx64.efi, which is required when Secure Boot is active, which in turn loads grubx64.efi).

We are fooling the PC by :
  •  Moving the Microsoft's boot loader (bootmgfw.efi) to some other location.
  •  Copying the shimx64.efi and grubx64.efi files to the original location of bootmgfw.efi(i.e before moving it).
  • Renaming the copied shimx64.efi file as "bootmgfw.efi" (so that binary behind the bootmgfw.efi name is of shimx64).
So from now on, when the PC is turned ON it will boot the bootmgfw.efi file but this file now has the binary of shimx64. Thus grubx64 will be loaded and the PC will boot into grub by default.



REASON FOR EACH STEP

 
Reason for Step 1 : We need to boot into Ubuntu first because all the changes we are going to make are through Ubuntu.

Reason for Step 2 : In order to make these changes, one must have superuser privileges. So second step is undertaken to become superuser.

Reason for Step 3 : Changes we are going to make are in the boot directory. A backup of this boot directory is to be created before we proceed so that if anything goes wrong, we have a backup.
I have created the backup by copying and pasting /boot as boot.bkp in the current working directory; you can have a destination of your own :
    cp -r /boot <destination path>

Reason for Step 4
: The idea behind this step is to move the Microsoft's bootmgfw.efi file (which is needed to boot windows) to some other location(but within the EFI partition only). In my PC, the location of this file is as mentioned in the command. If the location of this file is somewhat different in your PC, then change the path in the command accordingly :
    mv <file path> <destination path>

Reason for Step 5 : shimx64 is a simple program that provides a way to boot a computer with Secure Boot active.
grubx64 is the grub binary.
We need to copy these files to the bootmgfw.efi's original location(i.e. the location before moving it).

Reason for Step 6 : Rename the shimx64.efi file as bootmgfw.efi
What we have done so far is that we have fooled the PC(which boots bootmgfw.efi by default to load windows) to boot shimx64.efi by renaming shimx64.efi as bootmgfw.efi
So now, shimx64 will be loaded by default as bootmgfw which in turn will boot grub by loading grubx64.efi present in the same location.

Reason for Step 7 : Note that till now we have made the provision of booting into grub by default. Now the grub will identify both Windows and Ubuntu OS. So we need to configure grub such that when Windows is selected, it loads the Microsoft's bootmgfw.efi file which we moved to some location in Step -2.
open the file  /boot/grub/grub.cfg which is used to configure grub.

Reason for Step 8 : Find the line which says : chainloader <old path of Microsoft's bootmgfw.efi>
This line instructs the grub to load the file mentioned.
We need to change the filepath to the new path as per Step-2 so that when Windows is selected, the Microsoft's bootmgfw.efi is loaded(which is the binary for Windows OS).

 IMPORTANT NOTE

 

    Whenever there is an operation like update-grub or some updates in Ubuntu which leads to the regeneration of  grub.cfg file then the changes we made in Step 8 is undone. As a result of which, in GRUB menu, when Windows is selected then the GRUB is loaded again.

   So simply undergoing Step 8 solves the issue.



Hope this would solve the issue faced by many HP computer users and more, and make booting into the desired OS simpler.



Disclaimer : Above steps have been tested on hp - Pavillion 15-p073TX with Windows 8.1 and Ubuntu 14.04 as the installed OS.