Java Socket Porgramlama

Günümüzde kullanılan iki temel haberleşme protokolü bulunmaktadır.

UDP (User Datagram Protocol):
Bu potokol ile bağlantı oluşturmadan paket gönderip alabilirsiniz. Bağlantı kurulmadan haberleşildiğinden, haberleşmenin hangi soket(port) üzerinden yapılacağı bilinememektedir. Onun için paket içerisinde alıcı ve vericinin port bilgileride gönderilir. Bu da göndereceğimiz paket boyutunun artmasına sebep olmaktadır. TCP ‘ye göre daha az güvenilir bir protokoldür. Hangi paketin ne zaman iletileceği pek belli olmaz. Sonra yolladığınız bir paket hedefe daha önce yolladığınız bir paketten erken varabilir.

TCP (Transfer Control Protocol)
Bu protokol bir paket göndermeden önce hedef ile bağlantı kurmak gerekir. Bu da paket göndermeden önce bağlantı oluşturulması için zaman harcanması demektir. Bir kere bağlantı kurulduktan sonra istediğiniz kadar paket gönderebileceğiniz gibi gönderdiğiniz paket sayısı arttıkça bu protokolü kullanmaktan alacağınız verimde artacaktır. UDP protokolüne göre daha güvenilir bir haberleşme sunar. Zaten yapacağımız programlama örneklerinde de biz TCP protokolüne göre yapacağız.

Örneğimizin basit ve anlaşılır olması için, klasik “HelloWorld” benzeri bir örnek yapmayı uygun buldum.

Her habeleşmede olduğu gibi bir server ve bir de client tarafı olacak. Server tarafı, kullanıcının belirlediği bir mesajı yine kullanıcının belirlediği bir sokete yazacak. Daha sonra, client tarafı bu sokete ulaşıp, server tarafında kullanıcının belirlediği mesajı alıp ekrana yazacak. Bunu böyle yapmamın sebebi buna çok benzer bir uygulamayı çalıştığım şirket için yazacak olmam. Yoksa tabikide tam terside rahatlıkya yapılabilir. Yani server tarafı soketi okur ve client tarafı bu sokete birşeyler yazabilir. Hatta ikisinin belierlenmiş aralıklarla hem okuma hem yazma yapmasıda sağlanabilir ya da başka soket adresleri kullanılarak, bir soket clienta mesaj göndermek için başka bir sokette clienttan mesaj almak için kullanılabilir.

Kodun daha iyi anlaşılması için açıklamada bulunalım. Hem server, hem client aynı makinede koşacaklar. Yani ikiside host adresi olarak “localhost” kullanacak. İki uygulamada tek bir soket üzerinden haberleşecek. Soket numarası olarak 2222 kullanılacak. Client tarafında ekrana 10000 defa “Merhaba WordPress !!!” ve iterasyon numarası yazılacak. Server tarafında ise bağlantı ve server durumu ilei ilgili bilgiler yazılacak. İki class dosyası EchoServer.java ve EchoClient.java, iki tanede bu classları çalıştıracak olan mail fonksiyonların bulunduğu classlar olacak, EchoServerMain.java ve EchoClientMain.java. Önce server kurulacağı için EchoServerMain.java çalıştırılacak. Ardından ise EchoClientMain.java çalıştırılacak. Doğal olarak client çalışmadan server bağlantıyı tam olarak yapmayacak ve iterasyona başlamayacaktır. Ayrıca tek server tek client olacak. Fazladan client kullanmak istiyorsak Thread ler kullanılabilir.

İlk önce server classımızın nasıl olduğuna bakalım.

EchoServer.java

package server;

import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class EchoServer {
private ServerSocket echoServer;
private PrintStream outputsStream;
private Socket clientSocket;

public EchoServer(int port) {
try {
echoServer = new ServerSocket(port);
System.out.println("Server Builded");
} catch (IOException e) {
System.out.println("Port Error!!!");
e.printStackTrace();
}
}

public boolean openConnection() {
try {
clientSocket = echoServer.accept();
outputsStream = new PrintStream(clientSocket.getOutputStream());
System.out.println("Connection Establised!");

return true;
} catch (IOException e) {
System.out.println("Connection Error!!!");
e.printStackTrace();
return false;
}
}

public void putStringToSocket(String msg) {
outputsStream.println(msg);
}

public boolean closeConnection() {
try {
clientSocket.close();
System.out.println("Connection Closed!!!");
return true;
} catch (IOException e) {
System.out.println("Closing Error!!!");
e.printStackTrace();
}
return false;
}

public ServerSocket getEchoServer() {
return echoServer;
}

public void setEchoServer(ServerSocket echoServer) {
this.echoServer = echoServer;
}

public PrintStream getOutputsStream() {
return outputsStream;
}

public void setOutputsStream(PrintStream outputsStream) {
this.outputsStream = outputsStream;
}

public Socket getClientSocket() {
return clientSocket;
}

public void setClientSocket(Socket clientSocket) {
this.clientSocket = clientSocket;
}

}

Şimdi ise bu server classını build edecek ve ilgili fonksiyonları kullanıp bağlantıları oluşturacak main classımıza bakalım.

EchoServerMain.java

 package server;

public class EchoServerMain {
public static void main(String[] args) {
EchoServer server = new EchoServer(2222);
server.openConnection();
for(int i = 0 ; i < 10000; ++i){
server.putStringToSocket("Merhaba WordPress!!!  " + i);
}
server.closeConnection();
}
}

Sonra, serverımıza bağlanacak clientımızın class yapısına bir bakalım.

EchoClient.java

package client;

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

public class EchoClient {
private Socket clientSocket = null;
private BufferedReader bufferedReader = null;

public String getStringFromServer() {
try {
String responsString;
responsString = bufferedReader.readLine();
return responsString;
} catch (IOException e) {
System.out.println("IO Exception -- WriteBytes");
e.printStackTrace();
}
return null;
}

public boolean isConnected() {
return clientSocket == null &amp;&amp; bufferedReader == null;
}

public void openConnection(String hostName, int port) {
try {
clientSocket = new Socket(hostName, port);
bufferedReader = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));

} catch (UnknownHostException e) {
System.out.println("Unknown Host Exception");
e.printStackTrace();
} catch (IOException e) {
System.out.println("IO Exception");
e.printStackTrace();
}
}

public Socket getClientSocket() {
return clientSocket;
}

public void setClientSocket(Socket clientSocket) {
this.clientSocket = clientSocket;
}

public BufferedReader getBufferedReader() {
return bufferedReader;
}

public void setBufferedReader(BufferedReader bufferedReader) {
this.bufferedReader = bufferedReader;
}

public void closeConnection() {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}

Şimdi ise bu cilentı build edecek ve ilgili fonksiyonları kullanıp, servera bağlanacak main classımıza bakalım.

EchoClientMain.java

package client;

public class EchoClientMain {

 public static void main(String[] args) {
EchoClient client = new EchoClient();
client.openConnection("localhost", 2222);
for(int i = 0 ; i < 10000 ; ++i)
System.out.println(client.getStringFromServer());
client.closeConnection();
 }

}
 

İki main fonksiyonunu ardarda çalıştırdığımızda, client tarafında aşağıdakine benzer bir ekran çıktısı göreceğiz.


Merhaba WordPress!!!  9995
Merhaba WordPress!!!  9996
Merhaba WordPress!!!  9997
Merhaba WordPress!!!  9998
Merhaba WordPress!!!  9999

Server tarafında ise ekran çıktımız şu şekilde olacaktır.

Server Builded
Connection Establised!
Connection Closed!!!

Bu örnekler, Ubuntu altında Eclipse ile Java SE 1.6 kullanılarak gerçeklenmiştir. Çalıştırırken derlediklerinizi ayrı terminallerde çalıştırırsanız, ekran çıktılarınızı daha net bir şekilde görebilirsiniz ya da client main fonksiyonunun iterasyonunu kısaltabilirsiniz. İleride kodun Observer Pattern‘e uygun olarak geliştirilmesi amaçlanmaktadır.

End of Line