Karadeniz tekniK ÜNİversitesi BİLGİsayar mühendiSLİĞİ BÖLÜMÜ BİLGİsayar ağlari laboratuari



Yüklə 78,33 Kb.
Pdf görüntüsü
tarix17.10.2017
ölçüsü78,33 Kb.
#5099


 

 

KARADENİZ TEKNİK ÜNİVERSİTESİ 



BİLGİSAYAR MÜHENDİSLİĞİ BÖLÜMÜ 

BİLGİSAYAR AĞLARI LABORATUARI 

 

 

 



Soket Programlama 

 

  



1. Giriş 

 

JAVA dili süreçler arası iletişim için TCP ve UDP olmak üzere iki farklı soket yapısı 



kullanır.  Her  iki  soket  yapısı  da  haberleşmede  İstemci-Sunucu  (Client-Server)  mimarisini 

kullanır.  Bu  deneyde,  istemci-sunucu  soket  setlemeleri  ve  çoklu  kullanım  (multithreading) 

konularından bahsedildikten sonra TCP yapısına göre bir soket uygulaması üzerinde Üretici-

Tüketici (Producer-Consumer) probleminin çok iş parçacıklı (thread) çözümü üretilen kaynak 

yığına (stack) itilerek, tüketilen de yığından çekilerek gerçeklenecektir.  

 

2. Server Soket Setlemeleri 

 

 

Server Soket setleme adımları aşağıda verilmiştir: 



 

 



 

ServerSocket nesnesi türetme: 

servSock


 isimli 

ServerSocket 

nesnesi özel amaçlar 

için  ayrılmış  numaraların  dışında,  yani  1024-65535  arası  bir  port  numarası  seçerek 

aşağıdaki gibi oluşturulur: 

 

 



 

ServerSocket servSock = new ServerSocket(2861); 

 

 



 

Sunucuyu  bekleme  konumuna  getirme: 



servSoc



ServerSocket

  sınıfına  ait 



accept()

 metodunu kullanarak herhangi bir istemcinin bağlanmasını bekler. Bağlantı 

kurulduğunda 

link

 soket nesnesi şu şekilde türetilir: 

 

Socket link = servSock.accept(); 

 



 

Yollanacak  ve  alınacak  veriler  için  giriş/çıkış  (input/output)  katar  (stream) 

Setleme: İstemci bilgisayarlardan gelecek mesajları almak ve onlara mesaj göndermek 

için Socket sınıfına ait 



getInputStream

 ve 


getOutputStream

 metodları kullanılarak 



input

 ve 


output

 isimli stream nesneleri aşağıdaki gibi türetilir: 

 

 

Scanner input = new Scanner(link.getInputStream()); 



PrintWriter output = new PrintWriter(link.getOutputStream(), true); 

 



 

Veri  Gönderme  ve  Alma:  Soket  ile  veri  gönderme  ve  alma  işlemleri  için  sırasıyla 

println()

 ve 


nextLine()

 metodları kullanılır: 

 

output.println(“Gönderilecek karakter dizisi”); 

String message = input.nextLine(); 



 

Soket  bağlantısını  sonlandırma:  Bağlantı  Socket  nesnesinin 



close()

  metodu  ile 

aşağıdaki şekilde sonlandırılır: 

 

 



link.close(); 

 

 



 

3. İstemci Soket Setlemeleri 

 

 



Sunucu  ile  bağlantı  kurma  dışında  istemci  soket  setlemeleri  yukarıda  sunucu  için 

anlatılanlarla aynıdır. Sunucu ile bağlantı kurmak için 



link

 soket nesnesi sunucunun ismi (veya 

IP adresi) ve port numarası parametreleri yardımıyla aşağıdaki gibi türetilir: 

 

 



Socket link = new Socket(“SunucuAdı” , 2861); 

 

 



 

 

4. İstemci-Sunucu Uygulaması 



 

 

Kaynak  kodlardan  Soket  klasöründe  basit  bir  istemci-sunucu  uygulaması  verilmiştir 

(Tek istemci ve tek sunucu olacak şekilde çalışmaktadır). Uygulama test edilirken öncelikle 

TCPServer.java

  programı  koşularak  sunucu  başlatılır.  Daha  sonra 



TCPClient.java

 

koşularak istemci çalıştırılır ve sunucu ile bağlantı kurulur. Bu uygulamada istemci tarafından 



gönderilen  mesajlar  sunucu  tarafından  sayılır  ve  istemciden  “BYE  BYE”  mesajı  geldiğinde 

bağlantı  sonlandırılırken  toplam  mesaj  sayısı  yazılır.  Örnek  bir  program  çıktısı  aşağıdaki 

gibidir: 

 

 



SERVER

 

CLIENT

 

[0] Waiting for connection... 

[1] Connected to Server 

[3] Received Message : Merhaba 

[2] Enter message : Merhaba 

[5] Received Message : Nasılsın 

[4] Enter message : Nasılsın 

[7] Because of Received Message: BYE BYE 

 * Closing connection... * 

[6] Enter message : BYE BYE 

 

[8] SERVER > 3 messages received. 



* Closing connection... * 

 

 



5. Çok İstemcili Tek Sunucu Kullanımı 

 

Sunucu  bilgisayara  1‘den  fazla  istemci  bilgisayarın  bağlantı  kurması  durumunda 



sunucuda, her bir istemci için yeni bir is parçacığı başlatılmalıdır. Bunun için öncelikle 

Thread

 

sınıfı miraslanarak bir thread nesnesi türetilir. 



Start()

 metodu ile bu iş parçacığının yapacağı 

işin  kodunu  barındıran 

run()

  metodu  çağrılır.  Çok  sayıda  iş  parçacığı  aynı  anda  koşarken 

birbirlerine  zaman  ayırmaları  için 

sleep()

  metodu  kullanılır  ve  parametre  olarak  aldığı 

milisaniye kadar askıda durur.  

 

Kaynak kodlardan 



Multithreading 

klasöründe, biri ekrana 5 kere 



“Hello”

 diğeri de 



0-4

 arası sayıları yazan iki iş parçacığını çağıran 



ThreadHelloCount

 adlı java programı için 

örnek çıktı aşağıda verilmiştir: 

 

 




Hello! 



Hello! 



Hello! 

Hello! 


 

 



Yukarıdaki program çıktısına dikkat edilirse iş parçacıkları farklı sıklıklarla çağrılmıştır. 

Bunun  nedeni 



sleep()

  metodundaki 



Math.random()*1000

  ifadesidir.  Böylece  random 

fanksiyonu  ile  her  bir  iş  parçacığı 

0-1


  saniye  arasında  değişen  farklı  sürelerde  askıda 

durmaktadır. Dolayısıyla 



ThreadHelloCount.java

 adlı program her koşuşunda farklı bir çıktı 

üretecektir. 

 

Kaynak  kodlardan  Multithreading



 

klasöründe  daha  önce  anlatılan  soket 

uygulamasının  çok  iş  parçacıklı  uygulaması  verilmiştir. 

MultiServer.java

  programında, 

Thread

 sınıfını miraslayan 



ClientHandler 

sınıfı herbir Client bağlantısında bir iş parçacığı 

başlatmaktadır. 

MultiClient.java

  programı  soket  uygulamasındaki 

TCPClient.java 

ile 

hemen hemen aynıdır. 



 

 

6. Senkronize Edilmiş İş parçacıkları 

 

Farklı  iş  parçacıklarının  ortak  kullandıkları  kaynaklara  eşzamanlı  erişimleri  yanlış 



sonuçlar üretmeye neden olabilir. O yüzden ortak kaynaklara eş zamanlı erişimi engelleyecek 

bir  mekanizmaya  ihtiyaç  vardır.  Java  dili  bunu 



synchronized

  anahtar  kelimesi  ile 

gerçekleştirir. Örneğin aşağıdaki metodda ortak kullanılan 

sum

 adlı değişkenin aynı anda farklı 

iş  parçacıkları  tarafından  güncellenmemesi  için 

updateSum()

  adlı  metod  synchronized 

yapılmıştır.  

 

public synchronized void updateSum(int amount) 



sum += amount; 

 

Synchronized  bir  metodu  koşan  iş  parçacığına  o  anlık  bir  iş  düşmüyorsa 



wait() 

metodunu  çağırarak  synchronized  metod  üzerindeki  kilidi  kaldırır  ve  böylece  diğer  iş 

parçacıklarının da ilgili metodu koşmasına izin verir. Eğer bir iş parçacığı işini tamamlamışsa 

ve 


wait()

  konumundaki  başka  bir  iş  parçacığının  çalışmasını  sağlamak  istiyorsa 



notify()

 

metodunu  kullanır.  Wait  konumundaki  bütün  iş  parçacıklarının  çalıştırılması  için  de 



notifyall()

  metodu  kullanılır.  Bu  durumda  hangi  iş  parçacığına  öncelik  verileceğine  Java 

Virtual Machine (JVM) karar verir. 

 

6.1. Üretici-Tüketici (Producer-Consumer) Probleminin Soketlerle Gerçeklenmesi 

 

Bilindiği  gibi  üretici-tüketici  probleminde  üreticinin  ürettiği  ve  tüketicinin  tükettiği 



kaynak  ortak  kullanılmaktadır.  Burada  en  önemli  problem  kaynağa  eş  zamanlı  erişimi 

engelleyerek  tutarlılığı  sağlamaktır.  Üretici  ve  tüketicinin  ortak  çağırdıkları  metodlar 



synchronized

 yapılarak tutarlı bir kaynak güncellemesi yapılabilir.   




 

Üretici-Tüketici  uygulaması,  kaynak  kodlardan  Multi  Producer-Consumer  adlı 

klasörün içindedir. Üretici ve tüketicinin ortak erişeceği kaynağı (resourse) üretme ve tüketme 

işlerini yapan 



addOne()

 ve 


takeOne()

 metodları, 



Resourse.java

 programı içindedir. 

 

ResourseServer.java

 programı öncelikle 

item

 isimli bir 



Resourse

 nesnesi türetir ve 



Producer

 içinde 


item.addOne() 

çağrısı ile üretmeye başlar.  

 

Herhangi 



bir 

istemci 


tarafından 

sunucuya 

bağlantı 

kurulduğunda 



ResourseServer.java

  programında 



handler

  isimli  bir 



ClientThread

  threadi  başlatılır  ve 

istemcilerin  isteklerine  cevap  verilir.  İstemci,  Sunucuya  

1” karakteri  yolladıkça kaynakları 

tutan 


item

  nesnesinin 



takeOne() 

metodu  çağrılarak  kaynak  harcanır.  “0”  karakteri  ile  de 

bağlantı sonlandırılır. 

 

addOne()

 metodunda kaynak üretimi belli bir 

MAX 

(5) değerle sınırlandırılmıştır. Bu 

değere  ulaşıldığında 



wait

()  metodu  çağrılarak  istemcilerin  kaynağı  tüketmesi  beklenir. 

Herhangi  bir  kaynak  üretildiğinde  tüketilebilmesi  için 

notifyall()

  metodu  ile  istemcilere 

bilgi verilir. 

takeOne()

 metodunda da kaynak bittiğinde (değer 0 olduğunda) 



wait

() metodu 

çağrılarak  sunucunun  kaynak  üretmesi  beklenir.  Herhangi  bir  kaynak  tüketildiğinde 

üretilebilmesi için 



notify()

 metodu ile sunucuya bilgi verilir.      

 

 

7. Deney Hazırlığı 



 

1.

 



Socket  klasörü  içerisindeki 

TCPServer.java

  ve 


TCPClient.java 

uygulamalarını 

çalıştırarak  bir  istemci  ve  bir  sunucudan  oluşan    istemci-sunucu  uygulamasının  nasıl 

çalıştığını gözlemleyiniz. Soket nesnesinin nasıl oluşturulduğunu, soket yazma ve soketten 

okuma işlemlerinin nasıl gerçekleştirildiğini kavrayınız. 

2.

 



Multithreading 

klasöründeki 



ThreadHelloCount.java

 

kaynak  kodlarında  iş 



parçacıklarının  nasıl  oluşturulduğunu  ve  kullanıldığını  kavrayınız.  Aynı  klasördeki  çok 

istemci  tek  sunucu  uygulamasını  çalıştırarak  çok  istemciliğin  iş  parçacıkları  ile  nasıl 

gerçeklendiğini kavrayınız. 

3.

 



MultiClient.java

  programını  (Bölüm  6.1’de  anlatılan)  Multi  Producer-Consumer 

klasörüne  kopyalayıp  ismini 

ConsumerClient.java

  olarak  değiştiriniz  ve  gerekli 

değişiklikleri  yaparak    Multi  Producer-Consumer  uygulamasının  doğru  bir  şekilde 

çalışmasını sağlayınız. Yazdığınız programı deneye getiriniz.  

4.

 

Java  programlama  dilinde  yığın  veri  yapısının  nasıl  kullanıldığını  Stack  klasöründeki 



uygulamayı  kullanarak  kavrayınız.  Ayrıca,  ilgili  dilde  rastgele  sayı  üretiminin  nasıl 

gerçekleştirileceğini araştırınız. 

5.

 

Eclipse, JCreator, Netbeans gibi farklı IDE’leri kullanarak uygulamaları çalıştırabilirsiniz. 



Deney sırasında Eclipse kullanılacaktır. 

 

 



8. Deney Tasarımı ve Uygulaması 

1.

 



Deney sorularını cevaplayınız. 

2.

 



Deney uygulamalarını aynı makine üzerinde ve ağ ortamında çalıştırınız. 

3.

 



Aşağıda  detaylı  bir  şekilde  anlatılan  üretici-tüketici  problemini  çok  istemci  tek  sunucu 

mimaride  gerçekleyiniz. 



 


 

 



Resourse.java  programı  içindeki  addOne()  ve  takeOne()  metotlarında  gerekli 

değişikleri yaparak, 0..99 arası rastgele bir sayı olarak üretilen kaynak yığına itilirken 

PUSHED ITEM = ##”; tüketilen kaynak yığından çekilirken “POPED ITEM = ##” 

şeklinde mesaj yazılmasını sağlayınız (Burada ##, 0..99 arası bir sayıdır).  

 

Sunucunun (üretici) yığından çektiği değeri istemciye (tüketici) “YOU POPED = ##” 



şeklinde yollaması için gerekli değişiklikleri yapınız.   

 



Yığının  dolu  veya  boş  olduğu  bilgisini  “STACK  IS  FULL/EMPTY”  şeklinde  ekrana 

yazınız. 

 

Java  dilinde  yığın  veri  yapısının  nasıl  kullanılacağı  Stack  adlı  klasördeki 



StackImplement.java  isimli  kaynak  kodda  verilmiştir.  Herhangi  bir  programda  yığın 

veri yapısını kullanmak için java.util.* adlı paket dahil edilmelidir. 

 

İstemciden gelen isteklere (“1” kaynağı tüket emrini, “0” ise uygulamanın sonlanması 



emrini verir) bağlı olarak ResourseServer.java ve ConsumerClient.java programlarının 

ekran çıktısı aşağıdakine benzer olmalıdır: 

 

 

ResourseServer 



ConsumerClient 

PUSHED ITEM = 42 

Enter message ('0' to exit): 1 

PUSHED ITEM = 57 

SERVER> YOU POPED = 69 

PUSHED ITEM = 85 

 

PUSHED ITEM = 97 



Enter message ('0' to exit): 1 

PUSHED ITEM = 69 

SERVER> YOU POPED = 74 

STACK IS FULL 

 

 



Enter message ('0' to exit): 1 

 New client accepted. 

SERVER> YOU POPED = 41 

 

 



POPED ITEM = 69 

Enter message ('0' to exit): 1 

PUSHED ITEM = 74 

SERVER> YOU POPED = 16 



POPED ITEM = 74 

 

PUSHED ITEM = 41 



Enter message ('0' to exit): 1 

STACK IS FULL 

SERVER> YOU POPED = 97 



POPED ITEM = 41 

 

PUSHED ITEM = 16 



Enter message ('0' to exit): 1 

POPED ITEM = 16 

SERVER> YOU POPED = 85 



POPED ITEM = 97 

 

POPED ITEM = 85 

Enter message ('0' to exit): 1 

POPED ITEM = 57 

SERVER> YOU POPED = 57 

PUSHED ITEM = 70 

 

POPED ITEM = 70 

Enter message ('0' to exit): 1 

POPED ITEM = 42 

SERVER> YOU POPED = 70 



STACK IS EMPTY 

 

PUSHED ITEM = 12 



Enter message ('0' to exit): 1 

POPED ITEM = 12 

SERVER> YOU POPED = 42 

PUSHED ITEM = 34 

 

PUSHED ITEM = 1 



Enter message ('0' to exit): 1 

PUSHED ITEM = 85 

SERVER> YOU POPED = 12 

PUSHED ITEM = 34 

 

PUSHED ITEM = 55 



Enter message ('0' to exit): 0 

STACK IS FULL 

SERVER> Connection closed... 

Closing down connection... 

Closing connection... 

 

 

 



 


 

9. Deney Soruları 

 

1.



 

Soket kavramı, uçtan uca haberleşme ve TCP/UDP kavramlarını açıklayınız. 

2.

 

Çok istemcililiğin nasıl gerçeklenebileceğini açıklayınız. 



3.

 

addOne()

  metodundaki 

notify();

  satırı  kapatılırsa  nasıl  bir  problemle  karşılaşılır? 



Producer

 ve 


Consumer

 hangi sırada wait durumuna düşer? 

4.

 

takeOne()



 metodundaki 

notifyall();

 satırı kapatılırsa nasıl bir problemle karşılaşılır? 



Producer

 ve 


Consumer

 hangi sırada wait durumuna düşer? 

5.

 

Producer





addOne()

 metodunda hem 



wait()

 ile beklerken hem de 



notifyall()

 yaparken 

istemcilerin  kaynağı  tüketmesini  istiyor.  Buradaki 

wait()

  ve 


notifyall()

  çağrıları 

arasındaki fark nedir? 

6.

 



Consumer

take



One()

 metodunda hem 

wait()

 ile beklerken hem de 



notify()

 yaparken 

sunucunun kaynak üretmesini istiyor. Buradaki 

wait()


 ve 

notify()


 çağrıları arasındaki 

fark nedir? 

 



 

KARADENİZ TEKNİK ÜNİVERSİTESİ 

BİLGİSAYAR MÜHENDİSLİĞİ BÖLÜMÜ 

BİLGİSAYAR AĞLARI LABORATUARI 

 

 

2014-2015 Bahar Dönemi 

Soket Programlama Deney Raporu 

 

Grup No: 



 

NUMARA 

Ad ve Soyad 

 

 

 

 

 

 

 

 

 

 

 

 

 

1. Deneye Soruları  



 

 

Deney sorularını el yazısıyla cevaplayınız. 



 

 

 



 

 

Not: Deney raporu el yazısı ile bu şablon kapak sayfası olacak şekilde hazırlanacaktır. Raporlar, 

bir  sonraki  hafta  deneyine  kadar  teslim  edilebilir.  Kopya  raporlar  0  puan  alacaklarını  kabul 

ederler.  

 

Deney Sorumlusu: 

Çağatay Murat Yılmaz 

 

 



 

 

 



Yüklə 78,33 Kb.

Dostları ilə paylaş:




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©genderi.org 2024
rəhbərliyinə müraciət

    Ana səhifə