Yazan : Şadi Evren ŞEKER

1. Giriş
2. Sunucu / İstemci Mimarisi (Client /Server)
3. JAVA ile ağ programlama
4. JAVA dilinde veri iletişimi için akışların (streams) kullanımı
5. JAVA dilinde Temel bir istemci sunucu (client / server) kodlaması
6. Kodların derlnemesi ve çalıştırılması
7. Java dilinde çok lifli bir istemci / sunucu kodlaması
8. Kodların derlenmesi ve çalıştırılması

1. Giriş

Bu yazının amacı, JAVA programlama dili kullanarak basit bir istemci/sunucu mimarisinin kodlanmasıdır. Sunucu / istemci mimarilerinde birden fazla istemcinin bağlanması durumunda çok işlemli (multiprocess) veya çok lifli (multithreaded) kodlama uygulanır.

2. Sunucu / İstemci Mimarisi (Client /Server)

İstemci / sunucu (client / server) mimarisinde bir bilgisayarın istemci veya sunucu olması oynadığı role göre değişir. Yani bir sunucu bir ağ üzerinde bir hizmet sunan bilgisayardır. Örneğin bir web sitesi yada email sunucusu basitçe bu hizmetleri sunan bilgisayarlardır. Bu anlamda bir bilgisayar duruma göre istemci (client) ve duruma göre de sunucu (server) olabilir.

Birden fazla istemcinin aynı anda bağlandığı durumlarda, bir istemcinin, sunucu üzerinde yaptığı işlemlerin, diğer istemcileri engellememesi için (non-blocking); diğer programlamanın ve işletim sistemlerinin bize sunduğu birden fazla işlemin aynı anda çalışmasını sağlayan çok işlemlilikten istifade edilir.

Örneğin basit bir sisteme giriş işlemi sırasında bir kullanıcının ismini ve şifresini girmesi beklenirken, diğer kullanıcıların çalışmasına devam edebilmesi için çok işlemli programlama gerekir. Bu durumda istemcilerin her birisi için sunucu tarafında ayrı bir işlem oluşturulmalıdır.

JAVA programlama dilinde ne yazık ki işlem(process) oluşturma imkanı bulunmaz. Bunun sebebi JAVA programlarının üzerinde çalıştığı JAVA Çalışma Ortamının (JRE , Java Runtime Environment) zaten bir işlem olması ve bu işlem üzerinden yeni işlemler çalıştırıldığında kontrolünün mümkün olmamasıdır. Bu duruma çözüm olarak JAVA geliştiricileri, çok lifli (multi threaded) programlamaya izin veren bir ortam geliştirmişlerdir.

Kısaca java ortamında, bizim örneğimizdeki sohbet programı gibi, aynı anda birden fazla işin yapılması istendiğinde çok lifli (multithreaded) programlama kullanılır.

Yukarıdaki temel konuların açıklamasından sonra programlamaya başlayabiliriz. Programlama sırasında öncelikle ağ bağlantılarını kodlayacak, tek lifli bir ağ programını istemci / sunucu mimarisi ile geliştirdikten sonra çok lifli hale getireceğiz. Ağ olarak IP (internet protocol) üzerinde çalışan TCP (transport control protocol) kullanacağız (kısaca TCP/IP protokolü)

3. JAVA ile ağ programlama

JAVA dilinde ağ ile ilgili sınıflar (Class) java.net paketinin içerisinde toplanmıştır. Bu paketten ServerSocket ve Socket sınıflarını kullanacağız. Ağ programlama bilgisi olmayan okuyucular için burada belirtmekte yarar gördüğüm bir nokta, ağdaki IP (internet protocol) iletişiminin bilgisayarlarda bulunan portlardan yapılmasıdır. Bir portun bağlanması (binding) sonucu bu port soket (socket) halini alır ve bu soket üzerinden artık veri iletişimi olabilir. Yani bu durumu bilgisayarımızda çok sayıdaki deliğe benzetebiliriz (port). Bu deliklerden birisinin bir boru ile başka bir bilgisayara bağlanması durumunda, artık bu delikten bırakılan veriler diğer bilgisayara ulaşacaktır. Dolayısıyla bu delik artık bir soket olmuştur ve ucu bağlıdır.

Socket istemci;
 istemci = new Socket("Bilgisayar", PortNo);

Yukarıdaki kod, JAVA dilinde basit bir soket oluşturmaya yarar. Buna göre verilen parametrelerden ilki bilgisayar adıdır. Bu isim bilgisayarın ağ üzerinde bulabileceği bir isim (bilgisayar ismi (host name)) veya DNS üzerinden sorgulayabileceği bir isim (örn. bir web sitesi ismi) olabileceği gibi bir IP adresi de olabilir.

JAVA dilinde bulunan istisnalar (exceptions) gereği yukarıdaki satırı tek başına kullanmak mümkün olmaz. Bunun sebebi bir soket açılması sırasında karşılaşılabilecek giriş çıkış problemleridir (I/O). Bu durumu engellemek için JAVA’nın bize sunduğu imkanlardan try / catch bloklarını kullanmamız gerekir:

try{
 Socket istemci;
     istemci = new Socket("Bilgisayar", PortNo);
}catch(IOException e){
    System.out.println("Soket acilamadi");
}

Yukarıdaki kodun yeni halinde, try bloğunda bir problem olması durumunda catch bloğu çalışmakta dolayısıyla hata ekrana basılmaktadır.

Şimdiye kadar öğrendiklerimiz doğrultusunda artık iki bilgisayarın üzerinde bulunan deliklerden (port) birbirine bağlanabildiklerini ve bu bağlantı üzerinden veri akıtabildiklerini biliyoruz. Tam bu noktada bir problem söz konusudur. Şayet sunucu, istemcileri (clients) beklediği deliği (port) bir istemciye ayırırsa, bu delikten başka istemci bağlanamaz. Yani tek bir istemci gelip bu deliği tıkar ve yeni istemciler için bu delik artık doludur hatası oluşur.

Bu durumu çözmek için sunucunun konuştuğu ve istemcilerin bağlanmasını beklediği delik boş tutulmalıdır. Bu deliğin tek görevi gelen bağlanma taleplerini cevaplamaktır, sunucunun sunduğu hizmet ise pek ala diğer deliklerden sunulabilir.

Örneğin 800 numaralı portta çalışan bir sunucuyu ele alalım. Sunucu 800 numaralı porttan bir bağlantı gelmesini bekler, bağlantı olunca bu istemciyi hemen farklı bir porta, örneğin 801 alır ve iletişim bu port üzerinden devam eder. Yeni bir istemci bağlanınca da bir sonraki , örneğin 802 alarak bu işleme devam eder. İlk istemcinin işi bittikten sonra artık yeni gelen istemciyi 801 numaralı porta alabilir.

Bir anlamda 800 numaralı portta bekleyen sunucu gelen bağlantı taleplerini farklı portlara yönlendirerek bu portlardan hizmet sunar. Bu işleme kısaca port atlatma denilebilir. Bu işlemi yapmak için oturup baştan kod yazmak yerine JAVA’da bize sunulan nimetlerden birisi olan ServerSocket sınıfını kullanabiliriz. Bu sınıf bütün bu açıkladığımız işlemleri zaten yapmaktadır. Yani ServerSocket sınıfı verilen port numarasında beklemekte gelen bağlantıları bizim bilmediğimiz , bilmemiz de gerekmeyen portlara yönlendirmektedir.

Yukarıdaki temsili resimde gösterilen her iki bilgisayardaki deliklerin (port) bağlanarak soket haline gelmesidir. Bu resimde anlatılmak istenen, iki bilgisayar arasındaki deliklerin bir boru benzeri giriş ve çıkış akışlarının (InputStream / OutputStream) bağlanmasıdır.

ServerSocket sınıfından oluşan bir nesnenin kullanımı iki aşamadan oluşur. İlk aşamada nesneyi oluştururuz:

ServerSocket Sunucu;
 try {
    Sunucu = new ServerSocket(PortNo);
 }catch (IOException e) {
           System.out.println("Sunucu soketi acilamadi");
 }

Bu yazı şadi evren şeker tarafından yazılmış ve bilgisayarkavramlari.com sitesinde yayınlanmıştır. Bu içeriğin kopyalanması veya farklı bir sitede yayınlanması hırsızlıktır ve telif hakları yasası gereği suçtur.

Yukarıdaki şekilde açılan “Sunucu” isimli nesneyi kullanarak borularımızı (streams) bağlayabileceğimiz bir nesne oluşturmak için aşağıdaki kod yazılır:

Socket baglanti = null;
 try {
    baglanti = Sunucu.accept();
        }
 catch (IOException e) {
    System.out.println(e);
 }

Yukarıda, ilk aşamada oluşturulan Sunucu nesnesinin accept metodu çağrılarak bir bağlantı oluşturulmuş ve bu bağlantı bir sokete yönlendirilmiştir. Artık kodun bundan sonraki bölümünde baglanti nesnesine erişilerek sunucudaki veri iletişimi kontrol edilebilir.

4. JAVA dilinde veri iletişimi için akışların (streams) kullanımı

Ağdaki iki bilgisayarın birbiri ile konuşması için JAVA programlama dilinde bulunan akışlar (streams) kullanılır. Biz bu uygulamada DataInputStream ve PrintStream sınıflarını (class) kullanacağız. Bu uygulamanın geliştirilmesinde veya benzer ağ uygulamalarında farklı akış sınıfları kullanılabilir. Bu akış sınıflarını birer boruya benzetmek mümkündür. Basitçe iki bilgisayardaki delikler (ports) arasında köprü kurarlar ve birinden bırakılan veri diğerine ulaşır.

JAVA dilinde verilerin akması için kullanılan boruları (streams) ikiye ayırmak mümkündür:

  • Giriş akışları (InputStreams)
  • Çıkış Akışları (OutputStreams)

Öncelikle giriş akışlarını tanımlayalım. Bunun için iki ayrı tanım yapmamız gerekecek. İstemci tarafında “istemci” isimli soket nesnesinde bağlanan kodu aşağıdaki şekilde yazabiliriz:

DataInputStream input;
 try {
    input = new DataInputStream(istemci.getInputStream());
 }
 catch (IOException e) {
    System.out.println();
 }

Öte yandan sunucu tarafında “baglanti” isimli nesneden bir giriş akışı oluşturulacaktır:

 DataInputStream input;
 try {
      input = new DataInputStream(baglanti.getInputStream());
 }
 catch (IOException e) {
    System.out.println(e);
 }

Yukarıdaki kodların yazılması sonucu hem sunucu hem de istemci tarafında soketlerimizin arkasına boruları bağlamış oluyoruz. Artık bu input nesnesinden herhangi bir değer okunduğunda, istemci için sunucudan, sunucu için ise istemciden bir veri okunmuş olur.

Yukarıdaki üçüncü şekilde bulunan boruların bağlanması hatırlanırsa, giriş borularına benzer şekilde (ve karşılık gelecek şekilde) çıkış borularının da bağlanması gerekir. Bu bağlantı için aşağıdaki kodlar kullanılabilir:

PrintStream output;
 try {
    output = new PrintStream(istemci.getOutputStream());
 }
 catch (IOException e) {
    System.out.println(e);
 }

Yukarıdaki bağlama işlemi PrintStream sınıfı ile yapılmıştır. Bu sınıf aslında bir OutputStream tipidir. Uygulamamızda ve JAVA ağ iletişimi sırasında en çok yollanan veri tipinin String (dizgi) olduğunu kabul edebiliriz. Yukarıdaki printstream sınıfı bize java’nın en temel ekrana bilgi yazdıran System.out.println benzeri bir yazım imkanı sunar. Bu sayede yollamak istediğimiz verileri println fonksiyonunu çağırarak basitçe karşıya gönderebiliriz.

JAVA’da diğer bir alternatif ise yine bir OutputStream tipi olan DataOutputStream sınıfıdır. Bu sınıfta ise PrintStream’den farklı olarak String yerine byte tipi verileri yollamamıza izin verir.

 DataOutputStream output;
 try {
    output = new DataOutputStream(istemci.getOutputStream());
 }
 catch (IOException e) {
    System.out.println(e);
 }

5. JAVA dilinde Temel bir istemci sunucu (client / server) kodlaması

Yukarıdaki temel kodlamaları öğrendikten sonra çok lifli (multithreaded) programlamayı yine bir kenara bırakarak basit bir istemci / sunucu iletişimini kodlamaya çalışalım. Öncelikle çok tanıdık olan bir yankı sunucusu (echo server) yazalım. Literatürde çok geçen bu sunucu, kendisine gelen mesajları aynen istemciye geri yollar. Dolayısıyla istemcinin sunucuya yolladığı mesajlar bir anlamda yankılanmış olur. Basit bir şekilde teknolojiyi anlamak için oldukça elverişli bir örnek olan bu kodun istemci tarafı aşağıdaki şekilde kodlanabilir:

Yukarıda, kodumuzun istemci tarafı bulunuyor. Kodu inceleyecek olursak, ilk iki satırında ağ ve giriş çıkış işlemleri için gereken importlar yapılmıştır. Ardından 6 ile 19. Satırlar arasında kullanacağımız ağ bağlantısı ve bu bağlantıdaki akışlar (streams, borular) tanımlanarak birbirine bağlanmıştır. Buradaki bağlantıya dikkat edilecek olursa istemciSoket oluşturulmuş ve bu soket üzerine hem PrintStream hem de DataInputStream bağlanmıştır.

Sunucu olarak verilen 127.0.0.1 IP adresi localhost veya loopback olarak geçen bilgisayarın kendisidir. Yani bağlanmaya çalıştığımız sunucunun aynı bilgisayar olduğunu kabul ediyoruz. Şayet farklı bir bilgisayara bağlanılmak isteniyorsa buradaki IP veya bilgisayar ismi değiştirilecektir.

Yukarıdaki kod, bir önceki istemciye benzer şekilde 1234 numaralı portta bir soket oluşturmakta ve buradan gelen bağlantıları dinlemektedir. Sunucu, kodun 23. Satırında bulunan os.println fonksiyonu ile gelen mesajı geri yollamakta ve bu işi 21. Satırda açılan bir sonsuz döngü (loop) içerisinde yapmaktadır.

6. Kodların derlnemesi ve çalıştırılması

Kodların derlenmesi (compile) ve çalıştırılması aşağıdaki şekildedir:

Sunucu tarafı için:

İstemci tarafı için:

Unutulmaması gereken bir husus, sunucunun istemciden önce çalıştırılmasıdır. Aksi halde aşağıdaki şekilde bir hata alınabilir:

Bunun sebebi kodumuzda bulunan istisnanın (exception) tetiklenmiş olmsıdır. Çünkü bağlanılmak istenen bilgisayardaki ilgili portun arkasında soket bağlanmamıştır (bind).

Kodu test ederken, istemci tarafından bir mesajın yazılması yeterlidir. Bu mesaj sunucu tarafına ağ üzerinden iletilecek ve cevabı yine ağ üzerinden dönerek istemci tarafında ekrana yazılacaktır:

7. Java dilinde çok lifli bir istemci / sunucu kodlaması

Yukarıda basit bir ağ bağlantısının nasıl kodlandığını gördükten sonra esas amacımız olan sohbet programımızı yazmaya başlayabiliriz. Kodumuz, şimdiye kadar yazdığımız koda çok benzeyecek, sadece çok lifli (multithreaded) olmasını sağlayacağız. Dolayısıyla önce kodu verip sonra açıklamasını yapalım:

Yukarıdaki kodun büyük kısmı bir önceki uygulamamızla aynı olmakla birlikte, kodda yeni olan lif (thread) eklentileri bulunmaktadır. Öncelikle kodun bir lif (Thread) olarak çalışmasını sağlayan Runnable arayüzünü (interface) implement etmesi gerekmektedir. (kodun 4. Satırında)

Ayrıca bu ara yüzün (interface) gereği olarak sınıfımızda (class) bir run() metodu bulunması gerekir. Bu metod, kodun 37. Satırından itibaren kodlanmıştır. Bu metodun özelliği, lif çalıştığında bu fonksiyonun çalışmasıdır.

Kodun yeni olan bir diğer özelliği 25. Satırdaki yeni lif oluşturma satırıdır. Bu satırda new Thread() yazılarak yeni bir lif (Thread) oluşturulur ve içerisine sınıfımız (istemci sınıfı) olduğu gibi verilir.

Burada lif oluşturulup içerisine bir sınıfı verebilmek için sınıfın Runnable özelliğine haiz olması gerekir. Yani her sınıfı, bir lif oluşturup içine koymak mümkün değildir. Bunun için sınıfta bir run() metodu bulunmalıdır ve bu metodun bulunduğundan emin olmak için de Runnable ara yüzünü implement etmelidir.

Kodun 25. Satırından sonra artık bilgisayarımızda iki ayrı lif (thread) varlığından bahsedebiliriz. Birincisi sunucudan gelen mesajları ekrana basarken diğeri kullanıcının ekranda yazdıklarını (klavyeden yazıklarını) sunucuya yollamaktadır.

Yukarıdaki temsili şekilde de gösterildiği üzere birinci lif yani kodun kendisi, kullanıcı girişlerini okuyup sunucuya gönderirken (kodun 27. Satırı) ikinci lif ise, sunucudan gelen mesajları ekrana basmaktadır (kodun 40. Satırı) bu sayede bu iki iş birbirini engellememektedir.

Sunucu tarafında ise iki ayrı sınıf kullanacağız. Sınıflardan birisi sunucunun asıl çalışan ve bağlantıları toplayan lifi (thread) olacaktır. Diğer sınıf ise sunucunun gelen her bağlantıda oluşturduğu ve sadece ilgili istemciye cevap vermesi için kullandığı liften (thread) oluşacaktır. Önce ana sunucu sınıfımızın kodunu inceleyelim:

Yukarıdaki kod, daha önceden kullandığımız bağlantı ve borulama yaklaşımları ile 1234 numaralı porttan bir bağlantı olmasını bekler. Bu bekleme işlemi kodun 21. Satırında olmaktadır ve her bağlantı alınmasında, yeni bir istemciLif nesnesi oluşturulur.

Burada dikkat edilecek bir nokta toplam 10 adet liften oluşan bir dizinin (Array) varlığıdır. Kodun 8. Satırında tanımlanan ve 25. Satırında içerisine birer istemciLif nesnesi atanan bu dizide, bağlanan her istemci için bir nesne referansı (object referrer, gösterici (pointer) ) tutulur. Bu nesne göstericileri daha sonra istemciLifini incelerken de göreceğimiz üzere istemciler arası haberleşme sırasında kullanılır.

Diğer bir deyişle sunucuya bir istemci bağlandıktan sonra, bu istemci için oluşturulan lif (thread) artık sohbet ederken diğer liflerle haberleşir ve bizim ağ üzerindeki sohbet programımız aslında lifler arası sohbete dönüşür. Elbette her lif kendisine bağlanan istemciye, mesajları anında iletmekte ve dolayısıyla farklı ağ konumundaki kullanıcılar da bu mesajları almaktadır.

Yukarıdaki kodda, yapıcı metodun (constructor) içerisinde, anaSunucudan gelen lif bilgileri ve soket bilgisi, bu sınıfa geçirilmektedir. Yani yeni bir nesne (object) üretilirken, bu nesne anaSunucuda kurulmuş olan bağlantıyı almakta ve bu bağlantı üzerinden çalışmasına devam etmektedir. Ayrıca anaSunucuda bulunan diğer liflerin (threads) bilgisi de bu life geçmekte ve bu sayede lifler arasında mesajlaşma ile diğer liflerden gelen mesajları alabilmekte veya yeni bir mesajı diğer liflere iletebilmektedir.

Kodun 18. Satırında, istemciden yeni bir isim istenmekte 19. Satırda bu isim okunmakta, 21-23. Satırlarda ise bu bağlantı diğer liflere haber verilmektedir.

Bilindiği üzere anaSunucuda 10 elemandan oluşan bir lif dizimiz bulunuyor, bu liflerin tamamı o anda çalışmayabilir. Çalışanlara ise bağlanan kişiyi haber vermek üzere 21. Satırda basit bir for döngüsü (loop) kurulmuş, 22. Satırda ise o lifin varlığı sınanarak şayet böyle bir lif varsa 23. Satırda o life mesaj geçirilmiştir.

Bu satırdan sonra yeni gelen kişinin bağlandığı o anda çalışan herkese duyurulur. Mesajlaşmasının da bundan pek bir farkı yoktur. 24. Satırdaki sonsuz döngü içerisinde 25. Satırda ağdaki istemciden okunan mesaj, 27-28. Satırlarda benzer bir döngü ile bütün liflere iletilmektedir.

Yukarıdaki kodda, ayrıca /cik komutu ile kullanıcının bağlantıyı koparması hedeflenmiştir. Bunun için kullanıcı bağlanır bağlanmaz, istemcisine bilgilendirme mesajı 20. Satırda yollanmıştır. Ayrıca kullanıcıdan gelen her mesaj 25. Satırda okunduktan hemen sonra 26. Satırda bu mesajın /cik harfleri ile başlayıp başlamadığı kontrol edilmiştir. Şayet başlıyorsa, 24. Satırdaki sonsuz döngü kırılarak 31. Ve 32. Satırlarla kullanıcının sohbetten ayrıldığı diğer liflere bildirilmiştir.

8. Kodların derlenmesi ve çalıştırılması

Kodların çalışması ve derlenmesi aşağıda gösterilmiştir:

Sunucu tarafında:

İstemci tarafında:

Yukarıdaki kodların çalışan birer kopyası bu bağlantıdan indirilebilir.

Yukarıdaki kodlarda, Anatol URSU’nun sitesinden faydalanılmıştır. Bu kodlara http://www.ase.md/~aursu/ClientServerThreads.html adresinden de erişilebilir.

Yorumlar

  1. hilkat

    hocam cooook coook tesukkur ederım.Calısmalarınızın devamını dılıyorum.Emegınız ıcın de ayrıca tesekkur edıyorum...

  2. ibrahim

    Her şey için çok teşekürler ama benim bi sorum olacak bu sistemi iki farklı bilgisayarda (örneğin modem üzerinden birbirine bağlı bilgisayarlar) çalıştıramıyorum yani istemci sunucuya bağlanamıyor.(127.0.0.1 yerine sunucunun ip adresini yazdığım halde olmuyor.) Bu konu hakkında yardım edebilir misiniz? Çok teşşekürler...

  3. Şadi Evren ŞEKER Article Author

    kodu, mesajınızdan sonra kontrol ettim, kodda bir problem yok, belki ağ kurulumunuzda bir problem olabilir. Bilgisayarları bağladıktan sonra ping atarak verdiğiniz IP numaralarını kontrol edin.

    Şayet bilgisayarlar biribirni görüyorsa, sunucu tarafında programı çalıştırıp, istemci tarafından telnet ile bağlanmayı deneyin.

    Örneğin sunucu IP adresi 192.168.1.7 olsun, bu durumda aşağıdaki komudu istemci tarafından çalıştırabilirsiniz:

    telnet 192.168.1.7 1234

    elbette sunucu port numarasını koddaki 1234 şeklinde bıraktığınızı kabul edersek.

    Şayet istemci bu şekilde bağlanıp beklemede kalıyorsa sunucuya ulaşabiliyorsunuz demektir ve program çalışır, ancak bağlanamıyorsa, çok büyük ihtimalle ateş duvarı (firewall) ayarlarınızda ilgili portların kapalı olaması söz konusu olabilir.

    Umarım yardımcı olur

    Başarılar

    1. Guvercin

      Merhabalar öncelikle ellerinize sağlık. ben ToDoList programının daha basit halini yapacam. Bunu Netbeans ya da Eclipse de yapmam gerekiyor. Bunu Birçok kişi kullanabilir olması lazım. Şöyle anlatayım: Karşılıklı olacak. Ortak bir havuzda olur. Comment mantığı vardır, ya da thread de denir, yani eklenen maddeler vardır; ekleyeni, saati ve sırası bellidir, diğer kişi buna alt kırılım olarak cevap verir, bir diğeri de bu kırılımın da altında bir kırılım olarak cevap verebilecek Bir noktada karşılıklı olarak madde kapanır. Böyle bir proje yapmam lazım bunu nasıl yapabilirim yardımcı olursanız çok memnun olurum?

  4. Mesut AYDIN

    Şadi hocam öncelikle böyle bir site yaptığınız için size teşekkürlerimi iletmek istiyorum. Fırat üniversitesi bilgisayar mühendisliği öğrencisiyim. Ve sitenizden okul hayatım boyunca bir çok dersim için bir çok defa faydalandım. Birçok arkadaşıma tavsiye ettim. Spamcıların sitenize bulaşması benimde çok canımı sıktı. Umarım yaptıkları bu yanlış davranışı keserler.

    Gelelim soruma ;
    İnternet üzerinde online tavla tarzı birşeyler yapmaya karar verdim. Açıkcası pek yapabileceğimi zannetmesemde en azından gidebileceğim yere kadar gideyim diyorum. Ve sanırım bu online oyunlarda burda anlattıgınız mantık kullanılıyor. Acaba ben bu kodları sunucuya yuklesem appletlerle bir görsel sohbet ekranı yapsam çalışırmı ? Çalışmassa sanırım ip adres kısmına server ip adresini yazacam onun dışında yapmam gereken neler var.

    İyi günler.

    http://www.mesutaydin.org

  5. Şadi Evren ŞEKER Article Author

    Evet haklısınız, online oyunların çoğunda burada anlatılan istemci/sunucu (client/server) mantığı kullanılmaktadır.
    Yukarıdaki kodlarda applet teknolojisi kullanılmamıştır. Sizin uygulamanızda istemci tarafı (client) applet olacaktır. Bu sayede kullanıcılar istemci programını çalıştırıp bir uygulama (application) aracılığı ile sunucuya (server) bağlanmak yerine, sadece adresi belli bir web sayfasına girip buradaki appleti çalıştırmakla sunucuya bağlanacaktır. Kodlamada yapmanız gereken tek şey yukarıdaki kodları applet'e çevirmektir.
    Bu şekilde kodunuz çalışır ve benzer uygulamalar çalışmaktadır. Kodlama ile ilgil takıldığınız yer olursa yardımcı olmaya çalışırım.

    başarılar

  6. can

    selamlar ben daha önce applet seklinde bi sohbet programı yazdım client ve server olmak üzere 2 ayrı program wardı ip yi girince birbirlerine bağlanıyorlardı fakat bi sorun cıktı güvenlik daha sonra sanırım jre nin policy dosyasının içini biraz değiştirmem gerekiyordu oncelikle bu doğrumu doğgruysa bunu kod ile yapmanın bi yoluı olabilirmi yani applet e port acna vs yetkileri nasıl kazandırabilirim

  7. can

    bide hocam burada sunucuda belirtilen ip biraz acabilirmisiniz aynı ağda olan pc ler yada dünyanın farklı yerlerinde olanlar bide what is my ip deki ip olayı tesekkürler iyi calısmalar

  8. Şadi Evren ŞEKER Article Author

    Kod ile policy değiştirmek, benim bildiğim kadarıyla mümkün değil. Zaten mümkün olsa policy olmazdı ve ayrı bir ayara gerek kalmazdı. Buradaki kritik nokta, sizin verdiğiniz bu hakla bilgisayarınızı saldırılara açık hale getiriyor olmanız. Bunu ancak siz özel bir ayar ile yapabilirsiniz. Kod ile yapılacak olsaydı zaten böyle bir ayara gerek de kalmazdı.

    IP numarası, iki bilgisayarın gördüğü numaradır. Dünya üzerindeki IP numaranız veya yerel ağdaki IP numaranız. Sonuçta bilgisayarınıza örneğin ICMP paketi yollayabiliyorsanız birbirini görüyor demektir.

  9. can

    öncelikler zaman ayırdığınız için tesekürler .aslında tam olarak yapmak istediğim cok kullanıcılı tarayıcıda calisan basit bi oyun. fakat applet soket islemleri ile ilgili bir istisna fırlatıyor bunu nasıl asabilirim ?applet dısında bi alternatif warmı? iyi calısmalar

  10. Şadi Evren ŞEKER Article Author

    elbette istemci sunucu (client server) yapısında kodlama yapabilirsiniz. Oyun için bilgisayarlarda basit bir uygulama çalıştırarak bağlanılır.
    Diğer bir alternatif ise istemci tarafında applet kullanmak ama bilgisayarın kaynaklarına erişmemektir.

  11. Fire

    Merhaba
    paylaşımınızı inceledim çok kaliteli bir paylaşım ilkten bunun için teşekkür etmek istiyorum
    Şuan bende online teknik destek amaçlı bir program yazıyorum mesaj olayın yapıp test ettim local de bağlantı aldım kendi ağımdaki sanal pc ve kendi netbook'um da bağlantılar alabildim lakin sockete
    88. li gibi ip verdiğim zaman ne kendi ağımdaki bilgisayarlardan bağlantı alabildim nede başka ağdan bağlantı alabildim hep istisnalar aldım (connect refused nadirende connect timeout)
    modem firewall tüm giriş çıkış bağlantılarına açtım server kısmında firewallı kapattım
    clienti açtığım bilgisayarlardaki tüm firewalları kapattım öyle denedim sonuç hep olumsuz oldu
    yardımcı olursanız sevinirim iyi çalışmalar

  12. Şadi Evren ŞEKER Article Author

    İlginiz için öncelikle teşekkür ederim. Elbette kurulumunuzu görmeden tahminen birşeyler söylemek oldukça güç ancak sizin de bahsettiğiniz firewall ve ağ kurulumu akla ilk gelen problemler. Subnet ayarı yanlış olabilir veya yazdığınız IP adresine bağlantınız bulunmuyor olabilir. Bence, ulaşmak istediğiniz bilgisayara ping çekmeyi deneyerek başlamakta yarar var. Şayet ping ile (ICMP paketi) ulaşamıyorsanız zaten yukarıdaki program da çalışmayacaktır. Bu durumda öncelikle ağınızdaki problemi bulup çözmeniz gerekir. Şayet ping paketleri ulaşıyorsa ancak yukarıdaki program çalışmıyorsa, bu durumda soketlerde problem olabilir. Örneğin kodda bulunan sabit çakılmış 1234 gibi soket numaraları başka bir program tarafından kullanılıyor olabilir.
    Linux / Pardus işletim sisteminde bulunan nmap
    Windows işletim sisteminde bulunan netstat
    komutu bu durumda yardımcı olabilir. Yönetici hakları ile çalıştırdığınız komut satırında "nmap -a" veya "netstate -a" şeklinde komut verirseniz, bilgisayarınızdaki soket bağlantılarını görebilirsiniz. Bu bağlantılardan boş olan bir tanesini kullanmanız faydalı olacaktır.

    Şayet yukarıdakiler çözüm olmuyorsa, problemin daha farklı semptomlarını belirtin, belki başka bir problemdir ve bu yeni bulgular ışığında teşhis edebiliriz.

    başarılar

  13. mustafa

    hocam cok güzel dökümanlarınız var tesekkur ederim.
    ben bu kodu deistirerek sunucudan yankı yerine cevap vermesini sağladım ancak mesajların anında iletilmesinde sorun yasıyorum, yani ben istiyorum ki istemci ya da sunucu isterse ard arda cevap almadan mesaj gonderebilsin,bu konuda çözüm önerisi verebilir misiniz,
    yardımlarınız için tesekkur ederim.

  14. sahin

    3 ip arasında chat uygulaması kodları varmı acil lazım.Örneğin bi ipden nasilsin diye bi soru geldi diğer ip lere diğer 3 ipde bunu aynı anda iyiyim diye cevap verecek bu kodları istiyorum.Şimdiden Teşekkür Ederim..

  15. sahin

    Arkadaslar cok acil yukarda verdiğim örnegin kodları acil lazım. Yardımcı olursanız sevinirim.Şimdiden Allah Sizden Razı Olsun.Bu arada çalışmalarınız Çok güzel olmuş.Ellerinize Sağlık.Başarılarınızın devamını dilerim.teşşekkür ederim...

  16. Hamit

    Hocam paylasimlariniz icin tesekkur ederim. Isvecte programcilik okuyorum ve sitenizden bircok kez faydalandim. Bu aralar kayip lar ve kazanc larin database'e (MySql) kayit edildigi ve bir server üzerinden karsilikli oynanabilen "noughts and crosses"(15*15) oyununu kodlamaya calisiyorum. JAVA dilinde yeniyim ama sayenizde ustesinden gelecem gibi. Tekrar tesekkurler.

  17. Şadi Evren ŞEKER Article Author

    Sanırım bahsettiğiniz oyun tic-tac-toe olarak geçen oyunun bir çeşidi ve sitede bu oyunla ilgili bir kaç yazı zaten var, bir ararsanız belki işinize yarar birşeyler bulabilirsiniz.

    Başarılar

  18. Hamit

    Hocam ilginiz icin tesekkurler. Bi konuda fikrinize ihtiyacim var. oyun hazir. Lakin oyuncunun oyuna baslamasi icin Client-login kisminda username ve password girmesi gerekiyo. Yani client'in server uzerinden MySql e ulasmasi gerekiyo. bunu nasil yapacagimi teorik olarak aciklayabilirmisiniz. Simdiden tesekkurler

  19. Şadi Evren ŞEKER Article Author

    Bakın teorik olarak client yazılımları, uzaktan bir mysql sunucusuna (veya herhangi bir veritabanı sunucusuna) bağlanabilir. Ancak bu yöntem tercih edilmez çünkü veritabanı güvenliği ayrıca bir problem olur.

    http://www.bilgisayarkavramlari.com/2009/07/09/java-ile-veritabani-baglantisi/

    Yukarıdaki yazıda nasıl bağlanılacağı var. Burada sadece sunu adresini doğru girmeniz istediğinizi yapmak için yeterli.

    Ancak tavsiyem ve genelde yapılan, veritabanı işlemleri için sunucu tarafında bir java uygulaması yazıp, client (istemci) programın bu sunucuya bağlanması ve sunucunun veritabanına bağlanmasıdır. Diğer bir deyişle sizin sunucunuz veritabanına bağlansın ve istemciniz her ne istiyorsa sunucudan istesin.

    Başarılar

  20. memnune

    Hocam
    Yaptığınız site için size teşekkür ederim. Java da yeni sayılırım. Netbeans java ve mysql kullanarak bir program yaptım. jar haline getirdim. windows xp(bir) bilgisayarda çalışıyor.İkinci bir bilgisayarı tcp/ip ile birbirine bağladım. İkinci bilgisayar windows 7 (iki). İkinci bilgisayadan birinci bilgisayardaki jar dosyasını çalıştımak istiyorum. Fakat "could not find or load main class"
    hatası alıyorum. program içinde ip tanımlaması yapmadım. Yardımcı olabilir misiniz. Teşekkür ederim.

  21. Şadi Evren ŞEKER Article Author

    java da sizin alıntıladığınız hata mesajının anlamı, programınızda bir application bulunmadığıdır. yani konsoldan çalıştırdığınızda içerisinde bir main fonksiyonu olan kodunuz olmalıdır ki bu da :

    1
    
    public static void main(String args[]){

    şeklinde başlayan bir satırdır. Buradaki büyük küçük harf duyarlılığı önemli. Bu şekildeki fonksiyonu içermeyen class'lardı doğrudan çalıştıramazsınız. Tam olarak hangi dosyaları çalıştırıyorsunuz bilmiyorum ama sunucu kısmında anaSunucu.class ve istemci tarafında ise istemci.class dosyalarını çalıştırmanız gerekir. Yine de sorun yaşıyorsanız tekrar yazın yardımcı olmaya çalışayım.

    Başarılar

  22. ziyaretci

    merhaba yukarıda anasunucu sınıfında static clientThread[] = new clientThread[10];
    demişsiniz yani clientThread sınıfı türünde bir liste oluşturmussunuz ama sizin clientThread adında bir sınıfınız yok buna ek olarak istemciLif sınıfındada
    public istemciLif(Socket clienSocket, istemciLif[] t){
    this.clientSocket = clienSocket;
    this.t = t;
    }
    burada ise istemciLif[] türünde bir t istemişsiniz ama anasunucu tarafında metoda clientThread[] türünde bir t vermişsiniz şimdi soru şu hayali bir sınıf yazdınızda haberimiz yok acaba ?

  23. Şadi Evren ŞEKER Article Author

    Türkçe olarak anlaşılması için kodlarda Türkçe değişken ismi kullanmaya çalışmamdan kaynaklanıyor aslında clientThread ve istemciLif aynı sınıflar.

    Bu tip sorunlarla karşılaşılmaması için çalışan bir kodu yazının sonunda yayınlamıştım, indirerek çalıştırabilir ve kaynak kodu takip edebilirsiniz. Konu anlatımı sırasında ne yazık ki bazı terimleri Türkçe verirken böyle problemler olabiliyor.

    Başarılar

  24. Hasan

    Hocam çalışmanız çok bilgilendirici olmuş,peki bu kodlar wireless olarak çalışan bir ağ içerisinde kullanılabilir mi?Yani vermiş olduğunuz kodlar normal veya wireless olan bir ağ için aynımıdır yoksa wireless ağa özel olarak başka bir kod mu kullanmak gerekir?

  25. Şadi Evren ŞEKER Article Author

    Bahsettiğiniz fark (Wireless olup olmaması) fiziksel katman ile ilgili bir fark. Yukarıdak kodlar için fiziksel katmanın bir önemi yoktur. IP katmanı üzerinde çalıştıkları için birbirilerinin IP adreslerini görmeleri yeterlidir.

  26. Duman

    Hocam Tebrikler 2009 da yazdığınız Bir dökümana 2013 yılındada hala ilgi ile sorulan sorulara cevap verdiğiniz,Kişilere sordukları soruları aydınlatır şekilde cevaplar verdiğiniz,ve bunu gerçekten çok samimi bir uslupla yaptığınız için size binlerce kere Teşekkürediyorum..

  27. can

    merhaba hocam öncelikle elinize sağlık güzel çalışma bende android-java remote control uygulaması yapıyorum bende ekran çekme olacak örneğin android cihazda bilgisayarın ekranını alma ve temel mouse controlü yapma yalnız veri alıp yollama da direk bağlantı kesiliyor bu verileri nasıl sıkıştırıp alıp yollayabilirim şimdiden teşekürler...

  28. ismail

    Hocam öncelikle bu değerli paylaşımlarınız için teşekkür ederim. Ben chat programının görüntülü olanının yapmak istiyorum (msn benzeri) bunun için farklı programlara ihtiyaç varmı, yoksa netbeans programı ve içerisindeki kütüphaneler yeterlimi şimdiden teşekkürler kolay gelsin..

  29. serkan

    hocam paylaşımınız için öncelikle teşekür ederim elinize sağlık.
    Benim win üzerinde netbeans aracılığla yazdığım bir java socket projem var
    bunu linux da da çalıştırmam lazım gayette güzel çalışyır yanlız söcket iletişimleri
    gerçekleşmiyor. Bunun için bir izin feklan mı ayarlanmı öyle ise nasıl?

  30. Şadi Evren ŞEKER Article Author

    Evet firewall ve internet güvenliğine yönelik yazılımlar engelliyor olabilir. Ayrıca programınızdaki bağlantı kısmına bir exception handling ekleyerek çıkan sorunu ekrana bastırmayı deneyin. Tam olarak problem nerede çıkıyor hangi komut çalışmıyor bunları yazarsanız daha çok yardımcı olabilirim. Bir de sunucu tarafının çalıştığından emin olmak için bir port scanner (veya netstat benzeri birşeyler) kullanarak soket açılıp açılmadığına bir bakmanızda yarar var.

    Başarılar

  31. ömer özdemir

    Merhabalar çok güzel anlatmışınız yalnız ben php,mysql tarzı dosya uzantıları çalıştıracağım onunda kodunu paylaşır mısınız?

  32. Kerem

    Emeğiniz için teşekkür ederiz hocam;

    anaSunucu sınıfındaki static clientThread t[] = new clientThread[10]; hata veriyor hocam nereyi yanlış yapıyorumdur sizce?

    Hata: Cannot find Symbol diyor

  33. Kerem

    İkinci bir sorum İbrahim arkadaşımın dediği olayın nasıl yapıldığını merak ettim. Yani iki farklı bilgisayar arasında bu konu nasıl derleyip çalıştırdı?

  34. suatkulgi

    hocam size bi sorum olabilirmi günlerdir uğraşıyorum. bir cevapta bulamadım.
    çalışan bi oyun appletimde beyaz sayfa sorunu yaşıyorum. bu sorunun çözümünüde buldum.
    applet başlangıcında giriş buttonu koyup tıklandığında açılan yeni pencerede oyunu çalıştırabilirsem bu sorun kalkacak. Pencereyi açtırdım ama appleti içine çekemedim. muhtemelen basit birşeydir ama çözemedim 2 classım var biri şu:

    Class1:
    package client;
    import java.applet.Applet;
    import java.awt.Button;
    import java.awt.Frame;
    import java.awt.Graphics;
    import java.awt.Image;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import client.ClientAppletBase;
    import javax.swing.JFrame;

    import client.games.Player;
    import client.games.board.okey.OkeyDetailedInfoDialog;
    import client.games.board.okey.OkeyImageLoader;
    import client.games.board.okey.OkeyTheme;
    import client.gui.nith.DefaultImageLoader;
    import client.gui.nith.NithTheme;

    public class OyunpistApplet extends Applet implements ActionListener{

    String msg="";
    public OkeyClientApplet OkeyClientApplet;
    public Image image;

    public void init(){
    Button Evet,Hayır;
    Evet = new Button("Evet");
    Hayır = new Button("Hayır");

    //add buttons using add method
    add(Evet);
    add(Hayır);
    Evet.addActionListener(this);
    Hayır.addActionListener(this);
    }
    public void actionPerformed(ActionEvent ae){
    String str=ae.getActionCommand();
    if(str.equals("Evet")){
    msg = "Oyun Açılıyor";
    new OkeyClient();
    }
    else
    if(str.equals("Hayır"))
    msg = "Hayıra tıklandı";
    repaint();
    }

    public void paint(Graphics g){
    g.drawString(msg,10,100);
    }
    public class OkeyClient extends JFrame{
    public OkeyClient() {

    setTitle( "Okey Oyunları" );
    setSize( 800, 640 );

    //BU NOKTADA APPLETİMİ ÇALIŞTIRMAK İSTİYORUM

    setDefaultCloseOperation( EXIT_ON_CLOSE );
    setLocationRelativeTo( null );
    setVisible( true );

    }
    }
    }

    Yukarıdaki belirttiğim kısımda aşağıdaki Classı çalıştırmak istiyorum.

    package client;

    import java.awt.Frame;

    import client.games.Player;
    import client.games.board.okey.OkeyDetailedInfoDialog;
    import client.games.board.okey.OkeyImageLoader;
    import client.games.board.okey.OkeyTheme;
    import client.gui.nith.DefaultImageLoader;
    import client.gui.nith.NithTheme;
    public class OkeyClientApplet extends ClientAppletBase{

    public void showDetailedInfoDialog( Frame f, Player p ){
    (new OkeyDetailedInfoDialog(f, p)).show();
    }

    public DefaultImageLoader createImageLoader(){
    return new OkeyImageLoader(getDocumentBase());
    }

    public NithTheme createTheme(){
    return new OkeyTheme();
    }

    public String getMyGameName() {
    return "okey";
    }

    }

    şimdiden teşekürler

  35. veysi cengiz

    merhaba
    the method readline() from the type datainputstream is deprecated
    bu uyarıyı almaktayım nasıl çalıştırabilirim
    teşşekkürler

  36. Bilal Fedai

    Şadi hocam merhabalar ,

    Hocam makale ve youtube yayınlarınızı ilgiyle takip ediyorum , öncelikle verdiğiniz nitelikli ve verimli bilgiler için teşekkür ediyorum . Hocam sunucu istemci mimarili bir internet üzerinden haberleşen bi android mesajlaşma uygulaması geliştirmeye çalışıyorum .(Sunucunun statik ip atamasını ,port yönlendirmesini yaptım)Uygulamamanın istemci sunucu tarafı bitti burada bir problem yok ,mesajlar gayet hızlı bir şekilde sunucuya geliyor.

    Problemim şurada meydana geliyor (ki bu problem araştırdığıma göre yaygın bir problem) sunucuya gelen mesajı tekrar istemciye iletmek istediğimizde karşımıza istemci cihazın bağlı olduğu firewall problemi ve router'ın nat problemi ortaya çıkıyor.Bu sorunları aşmak için "TCP hohe punching" ,"STUN server" ve "ICE " gibi yaklaşımlar kullanılıyor .Ben şuan tcp hole punching yaklaşımını ele alıyorum . Sizden ricam bu konu hakkında biraz bilgi verebilir misiniz ?

    Teşekkürler

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir


+ iki = 3