Messenger v0.3 İstemcisi ve Kaynak Kodları

Messenger v0.3’ün sunucu kaynak kodlarını bu adreste 2 gün önce yayınlamıştım. Ardından vakit kaybetmeden birkaç satırlık veri gönderme-alma şeklinde test eden bir program olan istemciyi düzenleyerek, v0.2’nin görsellerinden de faydalanarak yeni bir soluk getirdim. v0.1 tadında, yani büyük çoğunlukla MIRC mantığıyla çalışan bu messenger’a da yine v0.2’de olduğu gibi kayıt olmak gerekiyor. Kendi sunucunuzda çalışacaksanız biraz önce verdiğim linkteki dosyalardan faydalanabilirsiniz, ya da bana söylerseniz size sunucuyu açarım:) (Bugün açık olacak:5 ağustos 2012)

Kullanmadan önce kayıt yapmanız gereken sayfa için tıklayın(kendi sunucunuzu kurarsanız kendi kayıt sayfanızı koymanız gerekecek, dosyalar aşağıda ve indirme linkinde mevcut, PHP ve MySQL tabanlıdır.)

Messenger’ı İndirmek İçin Tıklayın (Fix1 içerir, önceden indirdiyseniz güncelleyin.)

 

 

—— Burdan sonrası sunucu kurulumu ve kodlar içindir. ——

Windows altında sunucu kurmak isterseniz tıkla çalıştır sürümü için tıklayın(Bu sürüm bu şekilde çalışmayabilir, mümkünse python3 kurup alttaki kodlarla devam edin.)

Sunucu dosyaları, kayıt sayfası, istemci dosyalarını paket halinde indirmek için tıklayın.

 

Şimdi kodları ve bilgileri verelim:

import socket, json, time, threading
from tkinter import *

# Değiştirilecek ayar(lar)
sunucu = "www.ufakseyleratolyesi.com"
son_id = 0
ön_ek = ""
# Ayarlar bitti.

class giriş(threading.Thread):
    def run(self):
        yazi1.config(text = "Giriş Yapılıyor...\n")
        global kadı,şifre, ön_ek
        kadı = None; şifre = None
        while kadı == None or şifre == None:
            kadı = giriş1.get()
            şifre = giriş2.get()
        gonder = bytes(json.dumps((1,(kadı,şifre)),"utf-8"),"utf-8")
        soket = socket.socket()
        soket.connect((sunucu,4445))
        soket.send(gonder)
        sunucudan = soket.recv(8192)
        soket.close()
        sunucudan = json.loads(str(sunucudan,"utf8"))
        print("sunucudan gelen cevap: ", sunucudan)
        if type(sunucudan) != list:
            print("başarısız bağlantı")
            yazi1.config(text = "Giriş başarısız.\nTekrar deneyin.")
            başarısız(sunucudan)
        else:
            print("giriş başarılı.")
            print("kaldırma başlıyor.")
            ön_ek = sunucudan[1]+ " " + sunucudan[2] + ": "
            print("#### Ön ek: ",ön_ek)
            yazi2.destroy()
            giriş1.destroy()
            giriş2.destroy()
            yazi3.destroy()
            giriş3.destroy()
            print("kaldırma bitiyor.")
            pencere.update()
            başarılı(sunucudan)

class mesaj_gönder(threading.Thread):
    def run(self):
        mesaj = mesaj_girişi.get()
        mesaj = ön_ek + mesaj
        ssoket = socket.socket()    
        ssoket.connect(("www.ufakseyleratolyesi.com",4445))
        sgönder = bytes(json.dumps((2,mesaj)),"utf-8")
        print("gönderilecek mesaj:", mesaj)
        ssoket.send(sgönder)
        sgelen = ssoket.recv(8192)
        ssoket.close()
        return True

def mesaj_gönder_başla():
    aşama1 = mesaj_gönder()
    aşama1.start()

def başarılı(sunucudan):
    global konuşma_kutusu, mesaj_kontrol, mesaj_girişi
    mesaj_girişi = Entry(pencere)
    mesaj_girişi.pack()
    buton = Button(pencere)
    buton.config(text = "Gönder!",command = mesaj_gönder_başla)
    buton.pack()
    konuşma_kutusu = Text(pencere)
    konuşma_kutusu.config(width = 50)
    konuşma_kutusu.pack()
    pencere.geometry("450x600+100+100")
    yazi1.config(text = "Durumunuz: Online")
    mesaj_kontrol = mesaj_al()
    mesaj_kontrol.start()

class mesaj_al(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
    def run(self):
        while True:
            son_mesajları_al()
            time.sleep(0.5)

def son_mesajları_al():
    global son_id
    soket = socket.socket()
    soket.connect(("www.ufakseyleratolyesi.com",4445))
    gönder = bytes(json.dumps((3,son_id)),"utf-8")
    soket.send(gönder)
    gelen = soket.recv(8192)
    gelen = json.loads(str(gelen,"utf-8"),"utf-8")
    son_id += len(gelen)
    [konuşma_kutusu.insert(0.0,i+"\n") for i in gelen]
    soket.close()

def başarısız(sunucudan):
    pass
def karşılama():
    """Açılış ekranına döndürmeye yarar. Bişey döndürmez. Bir argüman almaz."""
    global yazi1,yazi2,giriş1,giriş2,yazi3,giriş3
    # Karşılama yazısı:
    yazi1 = Label(pencere)
    yazi1.config(text = "Messenger v0.3\nHoşgeldiniz...\n",\
                 font = "courier 17 bold", fg = "#0066FF")
    yazi1.pack()
    # Kullanıcı adı isteme ekranı:
    # Kullanıcı adı isteyelim:      giriş1= kullanıcı adı
    yazi2 = Label(pencere)
    yazi2.config(text = "Kullanıcı adı: ")
    yazi2.pack()
    giriş1 = Entry(pencere, highlightcolor="steelblue")
    giriş1.config(width = 40)
    giriş1.pack()
    # Şifre isteyelim:              giriş2 = şifre
    yazi3 = Label(pencere)
    yazi3.config(text = "\nŞifre: ")
    yazi3.pack()
    giriş2 = Entry(pencere, show="*", highlightcolor="steelblue")
    giriş2.config(width = 40)
    giriş2.pack(pady = 10)
    # Giriş butonunu koyalım.
    giriş3 = Button(pencere)
    giriş3.config(text = "Giriş yap", width = 20, command = giriş_ekran_başlat)
    giriş3.pack()
def karşılama_kaldır():
    """Giriş ekranını kaldırır. Bişey döndürmez. Bir argüman almaz."""
    pass

def giriş_ekran_başlat():
    global gir
    gir = giriş()
    gir.start()

pencere = Tk()
pencere.geometry("300x600+100+100")
pencere.title("Messenger v0.3 - Beta Aşaması")
# Logo kodları buraya gelecek
resim = PhotoImage(file="logo.gif")
img = Label(image=resim)
img.pack()
# Logo kodları burada bitecek
karşılama()
#
# Buraya animasyon vs. kodları gelebilir. Artık her ne konursa.
#
mainloop()

Aslında v0.1’den farklı olarak kayıt-giriş sistemi, şifrelerin md5 ile saklanması, biraz daha düzenli bir görünüm, kayıt sırasındaki isimle mesajların gönderilmesi, son mesajların otomatik olarak gösterilmesi(0.5 saniye yenilenme aralığı ayarlandı, kodlarda 0.5’i bulup istediğiniz sayıyla değiştirebilir, sunucu yükünü belirleyebilirsiniz.) ayarlandı. Sunucu çalıştığı andan itibaren tüm mesajların kapatılana kadar tutulması için ayarlama yapıldı. Fazlasıyla uzun bir sohbet planlıyorsanız son 50 mesajın sunucuda tutulması için şöyle bir kod bloğunu uygun yere eklemeniz gerekecek, ya da iletişime geçerseniz sizin için eklerim:

son_mesajlar = ["root: Sunucu Çalışıyor... Hoşgeldiniz."]
mesaj_id = 1
def mesaj_ekle(ip,mesaj):
    global mesaj_id
    son_mesajlar.append(mesaj)
    if len(son_mesajlar) => 50:
        del son_mesajlar[-1]
    mesaj_id += 1
    print("Son Mesajlar: ",son_mesajlar,end = "\n")
    return mesaj_id

En başta linkini verdiğim, en altta tekrar paylaşacağım sunucu kodlarındakimesaj_ekle() fonksiyonunu bu şekilde düzenlerseniz son 50 mesajı tutmaya başlar. Oradaki 50’yi istediğiniz sayıyla değiştirmekte tabii ki özgürsünüz.

Kayıt sayfası(HTML) kodları(indirme linki yukarıda var):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Kayıt Formu</title>
</head>
<body>
<table width="270" height="188" border="0" align="center">
  <form action="kayit.php" method="post">
  <tr>
    <td height="24">Adı</td>
    <td><input type="text" name = "adi" /></td>
  </tr>
  <tr>
    <td>Soyadı</td>
    <td><input type="text" name = "soyadi" /></td>
  </tr>
  <tr>
    <td>Mail</td>
    <td><input type="text" name = "mail" /></td>
  </tr>
  <tr>
    <td>Şifre</td>
    <td><input type="password" name = "sifre" /></td>
  </tr>
  <tr>
    <td>Tamam mı?</td>
    <td><input type="submit" value="Gönder!" /></td>
  </tr>
  </form>
</table>
</body>
</html>

Kayıt formunu işleyecek PHP sayfası kodları:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<meta http-equiv="Content-Type" content="text/HTML; charset= iso-8859-9">
<head>
<title>Kayıt Sonucu</title>
</head>
<body>
<?
//ob_start();
// POST ile gelen deðiþkenler alýnýyor.
$adi = $_POST['adi'];
$soyadi = $_POST['soyadi'];
$mail = $_POST['mail'];
$pass = $_POST['sifre'];
//Þifreyi md5 yapalým:
$pass = md5($pass);
function kayitli(){
    echo "<h1>Bu mail adresi ile daha önce kayýt olunmuþ!<br/> Geri dönüp tekrar deneyin.</h1>";
}
function boshata(){
    echo "<h1>Lütfen tüm boþluklarý doldurunuz!</h1>";
}
// MySQL baðlantýsý yapýlýyor.
include("config.php");
$baglanti = mysql_connect($sunucu,$kullanici_adi,$sifre);
@mysql_select_db($db_adi,$baglanti);
mysql_query("SET NAMES 'utf8'");
mysql_query("SET CHARACTER SET utf8");
mysql_query("SET COLLATION_CONNECTION = 'utf8'");
//mysql_query("SET NAMES 'utf8'");
// O mail adresiyle kayýt olunmuþ mu?
if(mysql_fetch_array(@mysql_query("SELECT * FROM kull WHERE mail = '$mail' "))){
    kayitli();
}
elseif (($pass == "") or ($mail == "") or ($adi == "") or ($soyadi == "")) {
    boshata();
}
else {
    if(@mysql_query("INSERT INTO kull(ad,soyad,mail,sifre,baglanti,istek,online,ip) VALUES('$adi','$soyadi','$mail','$pass','0','0','0','0')")){
    echo 'Kayýt baþarýlý!';}
    else {echo 'Bir hata meydana geldi! Fatal!';}
}
//ob_end_flush();
?>
</body>

PHP dosyası için MySQL ayarlarının yapılacağı config.php dosyası

<?
$sunucu = "localhost";
$kullanici_adi = "db_kullanıcı";
$sifre = "db_şifre";
$db_adi = "db_adı";
?>

MySQL sorgusu:

-- phpMyAdmin SQL Dump
-- version 3.5.2
-- http://www.phpmyadmin.net
--
-- Anamakine: localhost
-- Üretim Zamanı: 03 Ağu 2012, 02:37:40
-- Sunucu sürümü: 5.1.63-0ubuntu0.11.10.1
-- PHP Sürümü: 5.3.6-13ubuntu3.8

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;

--
-- Veritabanı: `vt`
--

-- --------------------------------------------------------

--
-- Tablo için tablo yapısı `kull`
--

CREATE TABLE IF NOT EXISTS `kull` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `ad` text NOT NULL,
  `soyad` text NOT NULL,
  `mail` text NOT NULL,
  `sifre` text NOT NULL,
  `baglanti` text NOT NULL,
  `istek` text NOT NULL,
  `online` text NOT NULL,
  `ip` text NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=15 ;

--
-- Tablo döküm verisi `kull`
--

INSERT INTO `kull` (`id`, `ad`, `soyad`, `mail`, `sifre`, `baglanti`, `istek`, `online`, `ip`) VALUES
(5, 'Güray', 'YILDIRIM', 'guray@gurayyildirim.com.tr', 'md5sifresansurlendi', '6,5,3,7,8,9,10,11', '0', '1', '78.191.18.55'),

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

Sunucuyu sadece derleyip yayınlamayı tercih etmedim. Sebebi ise benim linux sunucuda çalışmam ve sizin de bunu yapacağınıza dair inancım, zira pymysql modülünü Windows altında çalıştırmak istiyorsanız bile Linux altında 2to3’ten geçirmeniz gerekiyor, ya da ben Windows’ta yapamadım, her neyse. Kaynak kodları aşağıda, indirme linki yukarıda. Size tavsiyem sunucuyu bir linux server üzerinde çalıştırmanız. Ama ben MySQL kullanmak istemiyorum derseniz de sql yapısını sqlite3’e aktarıp devam edebilirsiniz. Python onunla birlikte geldiği için de ekstra bir işleme gerek kalmaz. Ama MySQL,  Fatih‘in beni birkaç dakikada ikna ettiği üzere çok çok daha kuvvetli ve gelişmiş bir yapıda, söylemedi demeyin.

Sunucu kodlarını verecek olursak:

import socket, json, threading, pymysql, hashlib
from mysql_bilgi import *

# odalar = {}
# odalar[1] = [1,2,["Naber la?"]]

class Sunucu(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.çalışıyor = 1

    def run(self):
        while True:
            try:
                self.soket = socket.socket()
                self.soket.bind((socket.gethostbyname(socket.gethostname()),4445))
                self.soket.listen(1000)
                while True:
                    self.gelen_toplu, self.gelen_ip = self.soket.accept()
                    self.gelen_veri = self.gelen_toplu.recv(1024)
                    if self.gelen_veri:
                        self.cevap = işle(json.loads(str(self.gelen_veri,"utf-8")))
                        print("\n\n Gönderilecek cevap satır 23:",self.cevap,"\n\n")
                        self.gelen_toplu.send(bytes(json.dumps(self.cevap),"utf-8"))
                    self.gelen_toplu.close()
                    if self.çalışıyor == 0:
                        self.soket.close()
                        break
            except:
                pass
            if self.çalışıyor == 0:
                break

# Adamın kayıtlı olup olmadığını inceleyelim:
def kontrol(ip,k_adı,şifre):
    """
    Veritabanına bağlanıp kullanıcı adı ve şifreyi kontrol eder. Kayıtlı değilse 1, kayıtlı ve şifre yanlışsa 0, ikisi de doğruysa sonucu döndürür.
    Kullanımı: kontrol(kullanıcı adı, şifre) şeklindedir. **Integer** döndürür.
    Not: Tablo adı "user" olarak ayarlanmıştır. Ana if yapısında else'in ilk satırından değiştirilebilir.
    """
    print("Kontrol() fonksiyonuna gelenler: ",ip,k_adı,şifre)
    ip = ip[0]
    şifre = hashlib.md5(şifre.encode()).hexdigest()
    bağlantı = pymysql.connect(host,dbuser,dbpass,db_adı)
    imleç = bağlantı.cursor()
    imleç.execute("SET NAMES 'utf8'")
    imleç.execute("select * from kull where mail = '{}'".format(k_adı))
    if imleç.fetchone() == None:
        return 1 # Kayıtlı değil için 1 döndürecek.
    else:
        imleç.execute("select * from kull where mail = '{}' and sifre = '{}'".format(k_adı,şifre)) # Şifre kontrol edildi.
        sonuç = imleç.fetchone()
        if sonuç == None:
            return 0 # Kullanıcı adı veya şifre hatalı.
        else:
            imleç.execute("update kull SET online = '1' WHERE mail = '{}' and sifre = '{}'".format(k_adı,şifre))
            imleç.execute("update kull SET ip = '{}' WHERE mail = '{}' and sifre = '{}'".format(ip,k_adı,şifre))
            print("Gelen baglanti IP'si:  ",ip)
            #imleç.execute("update kull SET online = '1' AND ip = '{}' WHERE mail = '{}' and sifre = '{}'".format(ip,k_adı,şifre))
            return sonuç # Başarılıysa sonucu gönderecek.
    imleç.close()
    bağlantı.close() 

# Adamın kayıtlı olup olmadığı incelendi.

# Mesaj ekleme ve son mesajların tutulması olayını halledelim.
son_mesajlar = ["root: Sunucu Çalışıyor... Hoşgeldiniz."]
mesaj_id = 1
def mesaj_ekle(ip,mesaj):
    global mesaj_id
    son_mesajlar.append(mesaj)
    mesaj_id += 1
    print("Son Mesajlar: ",son_mesajlar,end = "\n")
    return mesaj_id

def smesaj_yolla(içerik):
    sonid = içerik
    print("Bak buraya yazıyorum, smesaj_yolla fonksiyonundayım. Bilgiler: ",type(sonid),sonid)
    return son_mesajlar[sonid:]

def işle(veri):
    kod, içerik = veri
    print(kod,type(kod))
    if kod == 1:
        return kontrol(m.gelen_ip,içerik[0],içerik[1])
    if kod == 2:
        return mesaj_ekle(m.gelen_ip,içerik)
    if kod == 3:
        return smesaj_yolla(içerik)
    print("[satır 87]İstenen: ",kod,içerik)

Durum = "Henuz baslatilmadi"
while True:
    print(Durum)
    x = int(input("1 - Baslat / 2 - Durdur / 3 - Kapat\nGiris: "))
    if x == 1:
        m = Sunucu()
        m.start()
        Durum = "Sunucu Calisiyor."
    elif x == 2:
        m.çalışıyor = 0
        Durum = "Durduruldu."
    elif x == 3:
        m.çalışıyor = 0
        print("Sunucu kapatiliyor...")
        break

 

 
comments powered by Disqus