Bilgisayar sistemleri arası veri iletişimi, bu sistemlerden hizmet alan kullanıcılar ya da kullanıcıların işlettiği uygulama programları arası veri aktarımı amacıyla yapılır.

Bugün bir internet standartı olan ve çoğu platformda iletişim alt sistem standartı olarak yaygın bir şekilde kullanılan TCP/IP protokolü socket programlamada başlangıç noktamız olacaktır.

TCP/IP beş sıradüzensel katmandan oluşmaktadır. Bunlar: Uygulama, Ulaşım (Taşıma), Ağ, Veri Bağlantı katmanları ve Fiziksel katmandır. Bu katmanların ayrıntısını bilmemize şu an için gerek yok. Bir uygulamadan diğer uygulamaya gönderilmek istenen bir ileti bu katmanlar ile aktarılır.

TCP/IP katmanları

TCP/IP yazılımından, uygulamalar, socket olarak adlandırılan düzeneğe dayalı olarak hizmet alırlar. Uygulamaların birbiri ile iletişime geçmesi ve birbirlerine ileti gönderebilmesi için, kendilerinin TCP katmanına hangi adrese ileti yollanacığını bildirmesi gereklidir. Bu adres Bilgisayarın IP adresi ve kapı (port) numarası ile belirlenir. İleti, bilgisayarın IP adresiyle bilgisayara gider ve buradan hangi uygulama programına gideceği işte bu kapı numarası ile belli olur. Uygulama programlarının belirleyebileceği kapı numaraları 1024 ten 65535 e kadar herhangi bir değer alabilir. 1024 ten daha küçük numaralar Telnet, FTP, SNMP, gibi TCP/IP yazılımıyla birlikte sağlanan klasik hazır uygulamalara ayrılmıştır.

Sonuç olarak birbirleriyle iletişim içindeki uygulama programları {[IP numarası]:[Kapı numarası]} ikilisi ile ağ içinde biricik olarak tanımlanmış olur. Örn: (10.120.101.67:6161)

Bu bilgilerden sonra artık Java da socket kullanarak uygulama gerçekleştirmeye geçebiliriz.

Javada socket ile ilgili sınıflar java.net paketinde bulunur. Bu paket içerisindeki ServerSocket sınıfı sunucu socketi, Socket sınıfı da istemci socketi yaratmaya yarar.

ServerSocket

Sunucu programda, gelen istemci bağlantılarını dinlemeyi ve kabul etmeyi sağlar.

ServerSocket sSocket;
    try {
	sSocket = new ServerSocket(5555);
    } catch (IOException e) {
	System.out.println(e);
    }
    System.out.println("server waiting connection on port: 5555");
    try {
	Socket socket = sSocket.accept(); // burada bağlantı geliyor
	System.out.println(socket.getLocalAddress() + " connected");
	// bağlantı geldi, burada input ve output stream yaratarak iletişim sağlanabilir 
    } catch (IOException e) {
	e.printStackTrace();
    }

Bu kodun çalıştığı makinede 5555 numaralı port artık bu sunucu uygulamasına bağlanmıştır (herhangi bir sorun çıkmadıysa)

Belli bir port üzerinden socket açmaya kalkarsak ve bu port da daha önce başka bir uygulama tarafından kullanılıyorsa java.net.BindException hatası alırız. Bunun önüne geçmek için; ServerSocketi 0 parametresiyle yaratıp boş olan portlardan rastgele birisini kullanabiliriz. getLocalPort() methodu ile de hangi porttan açıldığını öğrenebiliriz.

		try {
			sSocket = new ServerSocket(0);
		} catch (IOException e) {
			e.printStackTrace();
		}		
		int myport = sSocket.getLocalPort();
		System.out.println("server waiting connection on port: "+ myport);
	        try {
		        Socket socket = sSocket.accept(); // burada bağlantı geliyor
		        System.out.println(socket.getLocalAddress() + " connected");
		        // bağlantı geldi, burada input ve output stream yaratarak iletişim sağlanabilir
	        } catch (IOException e) {
		        e.printStackTrace();
	        }

ServerSocket açıldığı port üzerinden gelen bir bağlantıyı accept() methoduyla kabul eder ve accept() methodu gelen bağlantı için yeni bir Socket yaratır. Yaratılan bu socket bağlantı yapan istemci ile iletişim kurmaya yarar.

Socket

İstemci programdan sunucu programa bağlantı oluşturmaya yarar. Bağlantı yapılacak programın(daha doğrusu programın ServerSocket’inin) Ip ve port adresi ile socket oluşturulur.

Socket socket;
    try {
           socket = new Socket("localhost", 5555);
    }
    catch (IOException e) {
        System.out.println(e);
    }

Bu şekilde daha önceden sunucuda 5555 numaralı portta açmış olduğumuz sunucu soketine bağlantı kurmuş oluyoruz.

Sunucu ve istemci tarafındaki socketlerin getOutputStream() ve getInputStream() methodlarını kullanarak DataInputStream, DataOutputStream, PrintStream, ObjectInputStream, ObjectOutputStream gibi istediğimiz akışları yaratarak socketler arası iletişimi sağlayabiliriz.

Bütün bu temel bilgilerden sonra artık sunucu ve istemci uygulamaları yazabiliriz 🙂 Aşağıda basit bir sunucu ve istemci programının tam kodları bulunmaktadır. Sunucu, kendisine bağlanan istemciden gelen stringin tamamını büyük harfe çeviriyor ve tekrar istemciye yolluyor.

Server.java

import java.net.*;
import java.io.*;

public class Server {
	public static void main(String[] args) throws IOException {

		ServerSocket serverSocket = null;
		try {
			serverSocket = new ServerSocket(5555);
		} catch (IOException e) {
			System.err.println("I/O exception: " + e.getMessage());
			System.exit(1);
		}
		System.out.println("Sunucu baslatildi. Baglanti bekleniyor...");
		Socket clientSocket = null;
		try {
			clientSocket = serverSocket.accept(); // bağlantı gelene kadar
							      // burada bekler
		} catch (IOException e) {
			System.err.println("Accept failed.");
			System.exit(1);
		}

		System.out.println(clientSocket.getLocalAddress() + " baglandi.");

		// input stream ve output stream yaratılıyor...
		PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
		BufferedReader in = new BufferedReader(new InputStreamReader(
				clientSocket.getInputStream()));

		String inputLine, outputLine;
		System.out.println("İstemciden girdi bekleniyor...");
		while ((inputLine = in.readLine()) != null) { // istemciden gelen string
							      // okunuyor...
			System.out.println("istemciden gelen :" + inputLine);
			outputLine = inputLine.toUpperCase(); // gelen string büyük harflere
							      // çevriliyor...
			out.println(outputLine); // büyük harflere çevrilen string istemciye
						 // yollanıyor...
			if (outputLine.equals("BYE")) // istemciden "bye" gelmişse döngüden çık.
				break;
		}
		System.out.println(clientSocket.getLocalSocketAddress()
				+ " baglantisi kesildi.");
		// stream ve socketleri kapat.
		out.close();
		in.close();
		clientSocket.close();
		serverSocket.close();
	}
}

Client.java

import java.io.*;
import java.net.*;

public class Client {

	public static void main(String[] args) throws IOException {

		Socket socket = null;
		PrintWriter out = null;
		BufferedReader in = null;

		try {
			socket = new Socket("localhost", 5555); // "localhost" ya da sunucu IP adresi
                        // input stream ve output stream yaratılıyor...
			out = new PrintWriter(socket.getOutputStream(), true);
			in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		} catch (UnknownHostException e) {
			System.err.println("Sunucu bulunamadı");
			System.exit(1);
		} catch (IOException e) {
			System.err.println("I/O exception:" + e.getMessage());
			System.exit(1);
		}
		System.out.println("Sunucuya baglanildi.");
		// klavyeden girdi: stdIn
		BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
		String userInput;
		System.out.println("Buyuk harflere cevrilmesi icin girdi bekleniyor (baglantiyi kesmek icin: bye) ...");
		while (!(userInput = stdIn.readLine()).equals("bye")) {
			out.println(userInput);
			System.out.println("Sunucudan gelen: " + in.readLine());
		}
		System.out.println("Baglanti kesiliyor...");

		out.close();
		in.close();
		stdIn.close();
		socket.close();
	}
}
Bu örnek program tam olarak sunucu-istemci mekanizmasını sağlamamaktadır. Örnekteki sunucu program aynı anda en fazla 1 tane istemciye hizmet verebilir. Birden çok istemciye hizmet verebilen daha gelişmiş bir örnek için TCP/IP Socket Programlama – Dama Oyunu – Dama Server (1/2) yazısının inceleyebilirsiniz.

Referanslar

  1. Ali Saatçi, Bilgisayar İşletim Sistemleri, “Dağıtılmış İşlem”
  2. All About Sockets – http://docs.oracle.com/javase/tutorial/networking/sockets/index.html
Etiketler: , , ,

4 Comments

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Bu site, istenmeyenleri azaltmak için Akismet kullanıyor. Yorum verilerinizin nasıl işlendiği hakkında daha fazla bilgi edinin.