Friday, July 26, 2013

Java: Sockets

Socket, defined by Oracle document, is one endpoint of a two-way communication link between two programs running on the network. A socket is bound to a port number so that the TCP layer can identify the application that data is destined to be sent.

What does this really mean?

Photo from The Bowery Boys

Imagine it is 1850. Rowland Hussey Macy, Macy's' store owner, is walking down the street of NYC when he notices strings hanging from several apartment complexes. 

"Excuse me, do you know what those strings are?" he asked a passerby. 

"They are can telephone lines. You attach cans to each end of the line and used it to talk to one another." 

"Intriguing. How far does it travel?"

"About half a mile." 

"Half a mile? I wonder....."

Photo by Jin Choi

As Mr. Macy walks back to the office, a plan begins to formulate. Two months later, he rented a small office across from Central park. The office has a window where people can come and request to talk to a representative. Because the window is small, only one person can come to the window at a time. To serve multiple clients at a time, Mr. Macy has the brilliant idea of using the can telephones. When a client needs to speak to a representative, she comes to the window. The representative at the window will give her a can telephone. She can use the telephone to speak with a representative inside of the office. This way, while Mary is talking on the side with one representative, Tom can comes to a window and request to speak to another. When Mary is done, she returns the can telephone so others can use it. 

Photo from Wiki

That is how I understand the socket. The building Mr. Macy rent is like the computer. It has many windows for many businesses. Macy can rent office 1 while Kohl rents office 2. The computer is the same way. It has many ports where an application can "rent/reserve" ports. From 0 - 1023, these ports are always in use, aka lifetime renter. You can't use these. But your application can rent any other ports from 1024+. Once you tell the computer you are using that port, no one else can use it. When a client need to speak to your application, it goes to the port that you "rent".



When you create a server, you need to create a ServerSocket. This socket is like the representative at the window, he is responsible for opening and closing the window(/port) and assigning request. He can also handle request, but if he is handling request, then no one will be able to speak to him, so it's best to hand the job to someone else.

The normal sockets are like the can telephones. When the client comes to your "window", you assigned a specific can telephone to him/her. That way, you can communicate freely. If I speak to socket one, I know I am talking to John because I assigned him that line. If I don't have sockets, I wouldn't know who I am talking to. When John is done talking to me, or I to him, we must close the socket so we can free up resources for other user. You can only talk to the client once.

This is what my server class looks like. Currently it accepts one client, returns "Hello, world!", then closes the sockets. After you run it, you can open your browser and go to http://localhost:4000 to see "Hello, world!"
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {

    public static void main(String[] args) throws IOException {
        Server server = new Server();
        server.start();
    }

public void start() {
        try {
           ServerSocket serverSocket = new ServerSocket(4000); //Representative at the window
            Socket clientSocket = getSocket().accept(); //Socket assign to client
            PrintWriter response = new PrintWriter(clientSocket.getOutputStream(), true); //get translator
            response.println("Hello, world!"); //Talk to client
            response.close(); 
            clientSocket.close(); //Return can telephone
            getSocket().close(); //close your window
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
One thing to note is the PrintWriter. When you call clientSocket.getOutputStream(), what you have to send to OutputStream are bytes. So PrintWriter is like a translator. You say, here's a string, translate it to bytes and give it to output stream.

0 comments:

Post a Comment