|
Evet arkadaşlar bugünkü programımızda Python programlama dilini kullanarak, Tkinter isimli sevgili modülümüz eşliğinde arayüz oluşturarak, socket modülü ile TCP uygulaması yapacağız.
Esas olan mantığı kavramak olduğu için TCP haberleşmesinde ne yaptığımız önemli değil. Ben kolay olsun diye şöyle birşey yapacağım şimdi:
İstemcimizde (client) kullanıcıdan bir sayı alacağız, sunucuya (server) göndereceğiz, sunucu sayının karesini alıp istemciye geri gönderecek. Yani kare alma sunucusu. Saçma oldu ama olsun 
Kullanım olarak ta, sunucuda program çalıştığında, sunucuyu çalıştır düğmesine basılınca sunucu çalışacak, istemci her sayı gönderdiğinde bağlantı kurulacak, sayı gidecek, cevap gelecek, bağlantı kapatılacak. Ve istemci “kapat” düğmesine bastığında hem istemcideki arayüz, hem sunucudaki arayüz kapanacak.
Bu uygulamayı windows ağı kurulu olan 2 bilgisayar arasında çalıştırdım. (virüs programlarını kapattım, firewall falan engelleyebilir belki)
Şimdi önce programımızın çalışmasını görelim, daha sonra adım adım kodları anlatalım.
Kodlarımızı .pyw uzantılı kaydettik. (konsolsuz çalışmayı sağlar, tıpkı .exe gibi)
İlk olarak sunucu_arayuz.pyw ‘ye çift tıklayarak programı açtık.
İnanamıyorum karşımıza şu çıktı. Çok şugar.

Şimdi istemcideki alici.pyw dosyasını çalıştıralım. (yani 2. bilgisayardaki)

Şu an 2 program da hazır. Herhangi bir bağlantı kurulmamış durumda. Hatta sunucu socket dinlemeye dahi başlamadı. Şimdi sunucuda “Kare alma sunucusunu calistir” tuşuna basıyorum, çalışıyor. Şu an socketten bağlantı talebi bekleniyor.
İstemcide 5 yazıp “kare” tuşuna basıyorum. Ve bağlantı kuruluyor, sonuç istemcide şöyle görünüyor:

Aynen devam:


Şimdi kapat tuşuna basalım. Hem istemci hem sunucu aynı anda kapanacak. (tabi kapandığı için resimle gösteremiyorum )
SUNUCU PROGRAMI:
from socket import *
from Tkinter import *
from sys import exit
def kareal():
p.config(text=”baglanti icin bekleniyor”)
b.config(text=”calisiyor”)
serversock=socket(AF_INET,SOCK_STREAM)
serversock.bind(ADDR)
serversock.listen(2)
while 1:
clientsock,addr=serversock.accept()
p.config(text=’baglanti geldi’)
islem=clientsock.recv(boyut)
if islem==”kare”:
a=int(clientsock.recv(boyut))
c=a*a
p.config(text=str(c))
clientsock.send(str(c))
clientsock.close()
elif islem==”kapat”:
break
serversock.close()
exit()
HOST=’169.254.151.72′
PORT=21567
boyut=1000
ADDR=(HOST,PORT)
ana=Tk()
ana.title(”Kare alma sunucusu”)
p=Label(text=”sunucu henuz calismiyor”)
p.pack()
b=Button(text=”Kare alma sunucusunu calistir”)
b.config(command=kareal)
b.pack()
ana.mainloop()
Haydi anlatalım.
İlk başta kullancağımız modülleri çağıralım.
from socket import * ile import socket arasındaki fark nedir?
import socket ile çağırdığınızda socket fonksiyonlarınız socket.fonksiyon() şeklinde çağırmanız gerekir. Diğer şekilde doğrudan fonksiyon() şeklinde çağırabilirsiniz. Yani from’lu olan daha kolay.
Socket modülü TCP uygulamalarımızı yönetecek, Tkinter Python için bir arayüz oluşturma modülüdür. Sys ile sadece programı kapatacağımız için yanlızca exit fonksiyonunu çağırdık.
Sunucumuzun IP’si: 169.254.151.72 Bunu biliyoruz.
Nasıl mı öğreniriz?
Eğer windows ağımız kuruluysa,
başlat>çalıştır>cmd
Kara tahtaya ipconfig yazınız.
Otomatik Yapılandırma IP adresi: 169.254.151.72 çıkıyor bende misal.
Evet HOST değişkenimize bu IP’yi yazıyoruz. Port olarak 21567 yazıyoruz. Boyut olarak da 1000 gayet güzel. Çok bile. (Paket boyutu bu, yani bir göndermede/almada ne kadar veri geleceği)
Şimdi programın arayüzü yöneten kısmındayız.
ana=Tk() ile ana penceremizi oluşturduk.
(Python’da her şey nesne olduğu için) ana.title ile (yani ana sınıfının title fonksiyonuna) programın ismini gönderdik ki bu arayüzde görünen isim oluyor.
Şimdi bir widget açıyoruz. p isimli bu widget bir etikettir. Yazıdır. Label diye açıyoruz.
p.pack() ile de widget’ımızı derliyoruz.
İkinci widget ise sunucuyu çalıştıracağımız düğme. Button ile b widget’ını açıyoruz. b nesnesinin config fonksiyonuna command değişkeni olarak düğmeye basıldığında çalışacak olan fonksiyon adını gidiyoruz. Yani düğmeye basılınca kareal fonksiyonu çalışacak.
b.pack() ile widget’ı derledik ve ana nesnesinin arayüzünü başlatacak olan mainloop fonksiyonunu çağırıyoruz.
ana.mainloop()
Evet efendim programımızın arayüzü bu kadar. Yani ilk baştaki (ilk resim) yapıyı böyle oluşturuyoruz. Şimdi düğmeye basılması durumunda neler olacak onları inceleyelim.
Tabi ki kareal() fonksiyonu çalışacak.
Kareal fonksiyonu adım adım:
- widget’ların text değişkenlerini config fonksiyonlarıyla değiştirerek basıldığı anda sunucu arayüzündeki yazıları değiştiriyoruz.
- Veri haberleşmesi için yapılacak şeyler, soket oluşturmak, adresi sokete yönlendirmek, soketi dinlemeye başlamak. Ve sonrası veri almak veri göndermek.
- socket(AF_INET,SOCK_STREAM) ile AF_INET ailesiyle SOCK_STREAM bağlantı tipini seçiyoruz.
- bind(ADDR) ile yönlendirmemizi (atamamızı) yapıyoruz.
- Ve en fazla 2 bağlantıyı kabul edecek şekilde soketi dinlemeye başlıyoruz.
- Dinleme başladıktan sonra bir sonsuz döngü içinde bağlantı bekliyoruz. (sonsuz döngü olması istemciden kapat komutu gelene kadar sonsuza kadar programın çalışmasını sağlıyor)
- Program, istemciden bağlantı talebi gelene kadar serversock.accept() satırında bekler. İstemciden bağlantı talebi gelir gelmez bağlantı kurulur. İsterseniz clientsock ve addr değişkenleriyle istemciyi görebilirsiniz.
- Bağlantı kurulduğu anda p widget’ı “bağlantı geldi” yazısıyla bizi uyarıyor. Gerçi o kadar hızlı değişecek ki göremeyeceğiz

- Programın çalışmasında aslında basit bir protokol oluşturmuş olduk. İstemcinin ilk gönderdiği veri yapılacak işlemi söylüyor. Onun için ilk veriye bakıyoruz. Eğer istemci kare diyorsa arkasından karesi alınacak olan sayının geleceğini biliyoruz ve clientsock.recv(boyut) ile 1000 boyutunda veri alımını başlatıyoruz.
- Bu haberleşmede kullanılabilecek olan veri string’dir. Yani istemciden gelecek olan sayı string gelecektir. Biz sayıyı int’e çevirip a değişkenine atıyoruz. Karesini alıyoruz. clientsock.send geri gönderirken de string haline çevirerek gönderiyoruz. Bu kadar kolay.
- Daha sonra bağlantıyı kapatıyoruz ve while döngüsünün başına gidiyoruz.
- Yani görüyoruz ki her kare hesabı için yeniden bağlantı kurup kapatıyoruz.
- İstemci kapat düğmesine bastığında bağlantı kurulunca ilk veri “kapat” kelimesi olacaktır. Bu durumda da gördüğümüz gibi while döngüsünü kırıyoruz ve programı kapatıyoruz. Kodları buraya yazarken tab’lar kaymış olabilir. Python’da tablar önemlidir biliyorsunuz. Program çalışmayabilir ona dikkat ediniz.
İSTEMCİ PROGRAMI
from socket import *
from Tkinter import *
from sys import exit
HOST=’169.254.151.72′
PORT=21567
boyut=1000
ADDR=(HOST,PORT)
def kare():
a=bgir.get()
tcpCliSock=socket(AF_INET,SOCK_STREAM)
tcpCliSock.connect(ADDR)
tcpCliSock.send(”kare”)
tcpCliSock.send(a)
e.config(text=tcpCliSock.recv(boyut))
tcpCliSock.close()
def cikis():
tcpCliSock=socket(AF_INET,SOCK_STREAM)
tcpCliSock.connect(ADDR)
tcpCliSock.send(”kapat”)
tcpCliSock.close()
exit()
ana=Tk()
e=Label(text=”Karesini almak istediginiz sayiyi girin:”)
e.pack(side=TOP)
bgir=Entry()
bgir.pack(side=LEFT)
d=Button(text=”kare”)
d.config(command=kare)
d.pack()
f=Button(text=”kapat”)
f.config(command=cikis)
f.pack(side=RIGHT)
ana.mainloop()
Sunucu programıyla büyük oranda aynı olduğundan daha özet anlatacağım.
Buradaki farklardan bizi arayüzdeki Entry() widget’ı. Kullanıcıdan sayı aldığımız yer yani. Bir de ikinci bir düğme var, kapat düğmesi. Widget’lardaki side değişkenleri ile de yerleşimi düzenleyebilirsiniz.
l Sayı girilip “kare” düğmesine basıldığında kare() fonksiyonu çalışıyor.
l Kare fonksiyonu önce kullanıcının girdiği değeri a değişkenine atıyor.
l Daha sonra bağlantıyı kuruyor ki dikkat ederseniz burada listen yok. Çünkü asıl beklemede olan sunucudur.
l Bağlantı kurulunca önce işlemi gönderiyorduk. “Kare” dizisini gönderiyoruz, sunucu şimdi sayı geleceğini biliyor.
l Arkasından sayıyı gönderiyoruz.
l Sunucu karesini alıp geri gönderiyor biz de alıyoruz. e etiketinin config fonksiyonuna gelen değeri gönderip kullanıcının sonucu görmesini sağlıyoruz.
l İlk kare alma işlemi için işler bitti. Bağlantıyı kapatıyoruz. Eğer başka sayı girilecekse yine bağlanacağız.
l Eğer kapatma düğmesine basılırsa, bağlanıp “kapat” dizisini gönderiyoruz. “kapat”ı alınca sunucudaki program kapanıyor, daha sonra da exit() ile istemci programı kapanıyor.
Gördüğümüz gibi çok zor ve karmaşık görünecek bir program aslında ne kadar kolay. Şüphesiz ki Python sayesinde bu böyle. Herşeyi kendisi yapıyor zaten.
Bu mantığı kavrayan kişi basit bir msn messenger dahi yapabilir. Aha! Yapsam mı acaba.
|
29 Ağustos, 2007 saat 12:15
büyüksün emrah, çok yararlı bir yazı olmuş. program pek bir işe yaramıyor
ama fonksiyonları güzel anlatmışsın
30 Ağustos, 2007 saat 21:10
Güzel olmuş eline sağlık. Aslında Google Code’da bir proje açıp eklesen daha ulaşılabilir olur. Hem svn ile daha rahat çalışırsın.
2 Eylül, 2007 saat 18:22
Olabilir aslında evet. Yapayım onu.
29 Kasım, 2007 saat 21:28
guzel demissin hos demissinde bi konuya daha acıklık getirsen mukemmel olucak ben postgresqle veri girmek istiyorum bunu nasıl yazabiliriöm soketle? karesini almak ve geri göndermek yerine karesini alıp hafızaya eklese nasıl olur yapılabilirmi??
30 Kasım, 2007 saat 02:44
orkut,
pythonla veritabanı çalışmadım hiç. ama yapılır tabi.
sunucu programında
a=int(clientsock.recv(boyut))var ya. işte verimiz a. python ile veritabanına nasıl bağlanılır onu araştıracaksın, fonksiyonları öğrenceksin. sonra a’yı o fonksiyona göndereceksin.kolaylıkla yapılır.
28 Haziran, 2008 saat 09:35
emrah arkadasım eline saglık cok iyi olmus…
ben daha yeni basladım hem python!a hemde bu soket programlamaya.ben yazdım ama calıştıramadım bunu.Asıl dosyaları gonderebilir misin bana .pyw uzantılısını.
Deniyorum hata veriyor…
kolay gelsin
28 Haziran, 2008 saat 14:25
celal, dosyaları tutmuyorum ben, silmişimdir.
kodları direk aldıysan çalışmaması normal. yazı içerisinde de belirtmiştim, python’da tab’lar önemlidir. kodları buraya geçirirken bütün tab’lar kaydı doğal olarak. onları ayarlaman lazım. yani hiçbir if’in while’ın çalışmaması lazım zaten bu şekilde.
artı, iki bilgisayar arasında çalışacak, IP’leri doğru girmen lazım.
yani baya bir düzenleme gerekiyor bu kodları tekrar çalıştırmak için.
28 Haziran, 2008 saat 16:05
tamam emrah sorunu çözdum.ufak bi yrde hata varmıs.O yuzden calışmıyormus.Ben de kocaeli üni. bilg. ögrt. okuyorum 4 e gectim şuan.Ayrıa bir şirketde de calışıyorum.Python ve soket programlama ogrenmem gerekıyor.Sende soket programalama ile ilgili kaynak var mı.Ama python yada C dili ikisinden biri.mail adresin varsa ekleyebilir miyim?
kolay gelsin
28 Haziran, 2008 saat 17:52
iyi bakalım, bende python kitabı vardı (mustafa başer), ama internetim yoktu onun için almıştım, bence internet yeterli. birsürü site var, hele ingilizcen varsa hiç sıkıntı çekmezsin. soket programlama ile ilgili hiçbir şey yok elimde.
bir sorun olursa iletişim formundan sorabilirsin, eposta adresinden yanıtlarım direk, eklersin. (buradan vermiyim)