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