/**************************************************************************************************
* Create a TCP/IP server (a single connection)
* TCP server communication uses both a TCP server socket object and a TCP client socket object.
* A TCP server socket object is used to maintain an open socket connection to all clients.
* Using the accept() method, a TCP server socket will establish a new client socket. 
* When a TCP client socket is created you are assigned a port number by the O/S (next port#).
*
* PS. This server takes whatever the client sends, and returns it in uppercase
*
* Usage: TCPserver <serverPort>
* 
* @version 1.0
* @author Sam Sultan
***************************************************************************************************/
import java.io.*;
import java.net.*;

public class TCPserver
{
    public static void main(String[] args)
    {
        if (args.length != 1) {
            System.out.println("Usage: TCPserver <serverPort>");
            System.exit(0);
        }
    
        InetAddress serverIP;           //IP address object for server
        InetAddress clientIP;           //IP address object for client
    
        int serverPort;                 //server port for listening
        int clientPort;                 //port number for client

        ServerSocket listenTCPSocket;   //TCP socket for listening
        Socket       TCPSocket;         //TCP socket for communication

        String recvString;              //string received from client
        String sendString;              //string to send client

        try 
        {
            serverIP   = InetAddress.getLocalHost();    //get local server address
            serverPort = Integer.parseInt(args[0]);     //get server port number        

            System.out.println("Server Host Name.....: " + serverIP.getHostName());
            System.out.println("Server IP Address....: " + serverIP.getHostAddress());
            System.out.println("Server Port Requested: " + serverPort);

            listenTCPSocket = new ServerSocket(serverPort);     //socket for listening 

            System.out.println("Server Port Listen on: " + listenTCPSocket.getLocalPort());
            System.out.println();

            System.out.println("Waiting for client connection...... \n");

            TCPSocket = listenTCPSocket.accept();               //creating a Socket
                                                                //from the ServerSocket

            System.out.println("Client connection opened to:");

            clientIP    = TCPSocket.getInetAddress();           //get client IP address
            clientPort  = TCPSocket.getPort();                  //get port assigned to client 

            System.out.println("Client Host Name.....: " + clientIP.getHostName());
            System.out.println("Client IP Address....: " + clientIP.getHostAddress());
            System.out.println("Client Port Assigned.: " + clientPort);
            System.out.println();

            InputStream        socketIn1 = TCPSocket.getInputStream();          //ref to socket input 
            InputStreamReader  socketIn2 = new InputStreamReader(socketIn1);    //convert to 16 bit
            BufferedReader     socketIn  = new BufferedReader(socketIn2);       //to use readLine()

            OutputStream       socketOut1 = TCPSocket.getOutputStream();        //ref to socket output 
            OutputStreamWriter socketOut2 = new OutputStreamWriter(socketOut1); //convert to 16 bit
            PrintWriter        socketOut  = new PrintWriter(socketOut2);        //buffered and can use println()

            while(true)
            {
                /*------------------ receiving data ---------------------*/
    
                System.out.println("Waiting for client input from.... "
                                   + clientIP + ":" + clientPort);
                System.out.println();

                recvString = socketIn.readLine();       //receive data from the socket

                if((recvString==null) || recvString.trim().length()==0)  //empty 
                    break;      

                System.out.println("Received..: " + recvString);

                /*------------------ sending data ---------------------*/
    
                sendString = recvString.toUpperCase();

                System.out.println("Sending...: " + sendString ); 
                System.out.println();

                socketOut.println(sendString + "\n\n");   //send data thru the socket with 2 newline     
                socketOut.flush();                        //flush buffer
            }

            System.out.println("Closing connection to: "+ clientIP +":"+ clientPort);
            socketIn.close();
            socketOut.close();
            listenTCPSocket.close();
            TCPSocket.close();
        }
        catch(IOException e)
        {
            System.out.println("I/O error: " + e );
            System.exit(-1);
        }
    }
}