Forum: Diğer Konular RSS
Tcp/Udp ve Ağ Programlama Öğrenmek
Sayfa:  1  2  sonraki 
İbrahim #1
Üye Eki 2015 tarihinden beri · 156 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Tcp/Udp ve Ağ Programlama Öğrenmek
Merhaba;

Ben skype vb. gibi uygulamalar hazırlamak için ağ programlamayı öğrenmek istiyorum. Bunun için Qt kullanıyorum. Sitesinden Tcp ve udp sınıflarını okuyorum fakat mantığını tam olarak anlamıyorum. Yani görüntülü konuşma ve chat sistemleri için bildiğiniz kaynaklar nelerdir?

Teşekkürler!
acehreli (Moderatör) #2
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Kaynak bilmiyorum ama bence uygulama programcısı için gereken kavram şu:

  • Sunucu bir port üzerinde bekler

  • İstemci o porta bağlanır

  • İkisi birbirlerine mesaj gönderirler

İlk iki madde en alt düzeyde soketlerle hallediliyor ama genelde programcının o kadar alt düzeye inmesi gerekmiyor. Örneğin, Phobos'ta std.socket modülü kullanılabilir. Şöyle bir örnek program yazmıştım:

  http://ddili.org/ornek_kod/istemci_sunucu.d

Aslında o program gereğinden karmaşık çünkü sunucu, koşut olarak bile çalışıyor.

Ali
İbrahim #3
Üye Eki 2015 tarihinden beri · 156 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Verdiğiniz D kodu için teşekkürler. Aslında benim anlatmak istediğim şey Qt dışında, yani benim asıl bilmediğim Bu görüntülü konuşma nasıl oluyor? Chat sistemlerinde zaten yazı falan gönderip alıyorlar. Peki görüntüleri webcamdan nasıl gönderiyorlar? Yani istediğim kaynak aslında Qt değil de bu uygulamaların nasıl yapıldığına dair bir kaynak. Tcp ve Udp öğrenmeye çalışıyorum ama nafile. Görüntülü konuşmayı bir türlü anlamadım örnek de bulamadım doğru dürüst.
Teşekkürler!
acehreli (Moderatör) #4
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
İbrahim:
Peki görüntüleri webcamdan nasıl gönderiyorlar?

Hiç bilmeden :) cevaplıyorum:

  • Kamera cihazı var

  • Kamerayı yöneten bir sürücü (driver) var; bu, donanım adreslerine yazarak ve okuyarak etkileşir

  • Bu sürücü ile etkileşmeye yarayan bir kütüphane var; böylece donanımla uğraşmak zorunda değiliz

  • Bu kütüphanenin "görüntü karesi hazır olunca benim yazdığım şu işlevi çağır" demeye yarayan bir işlevi (API'si) var

  • Programcı bir bellek parçası ayırıyor; o API işlevini çağırarak kendi işlevini tanıtıyor; kendi işlevi çağrıldıkça da belleğine okunmuş olan görüntü karesini öteki tarafa soket üzerinden gönderiyor

  • Karşı taraf aldığı görüntü karesini kendi tarafındaki görüntüleme cihazına yazıyor

Ali
İbrahim #5
Üye Eki 2015 tarihinden beri · 156 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Teşekkürler, aslında webcamdan nasıl gönderiyorlar deyince yanlış anlaşıldı. Kamerayı zaten Qt içindeki QCamera sınıfı ile yapabiliyorum:
QCamera* camera = new QCamera();
QCameraViewfinder* viewfinder = new QCameraViewfinder();
 
camera->setViewfinder(viewfinder);
viewfinder->show();
camera->start();

Fakat görüntülü saohbet ve chat yapmak için sanırım tcp ve udp yani ağ programlamayı bilmem gerekiyor eğer doğru biliyorsam tabi.
    Programcı bir bellek parçası ayırıyor; o API işlevini çağırarak kendi işlevini tanıtıyor; kendi işlevi çağrıldıkça da belleğine okunmuş olan görüntü karesini öteki tarafa soket üzerinden gönderiyor


    Karşı taraf aldığı görüntü karesini kendi tarafındaki görüntüleme cihazına yazıyor
Burada soket üzerinden nasıl gönderilidiği ve kendi cihazına nasıl yazıldığı gibi bilgileri bilmediğim için bunları öğrenmek istiyorum aslında. Teşekkürler!
acehreli (Moderatör) #6
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Soket iletişimi belirli bir tarif üzerine işleyen bir düzenektir. Her programlama dilinde aynıdır. Bence "soket programlama" diye aratınca çıkan bilgiler hangi dilde olursa olsun aşağıdakileri içerir:

  • Sunucu sırasıyla şunları yapar: Önce bind, sonra listen. Bağlanan her istemci için de accept.

  • İstemci de sırasıyla şunları yapar: connect

Bu noktada artık bağlanmışlardır. send ile veri gönderirler, recv ile veri okurlar. Gerçekten temelde bundan başka bilgi gerekmiyor. :)

Ali
İbrahim #7
Üye Eki 2015 tarihinden beri · 156 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
İşte istediğim bu. Teşekkürler!
Peki güvenlik sorunları olur mu? Olursa ne sorunlar olur? Çünkü bir yerde okuduğuma göre crypt etmek falan gerekiyormuş (chat sistemi için).
acehreli (Moderatör) #8
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Tabii ki güvenlik sorunu olur. Tam güvenli olan hiçbir cihaz yok ki. :)

Örneğin, bilgiyi açık olarak gönderirsek herkes (örneğin, aynı şebekeyi paylaşıyorsak kapı komşusu) görebilir. Bence bu konuyu sonraya bırakabilirsin. Önce bilgi alış verişini sağla, sonra tam çıkış noktasında şifrelersin.

Ali
İbrahim #9
Üye Eki 2015 tarihinden beri · 156 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Tekrardan merhaba Ali hocam;

Sorunlarla karşılaşmaya devam ediyorum. Mesela Qt sistesinde şöyle bir örnek var: http://doc.qt.io/qt-5/qtnetwork-network-chat-example.html

Bu sayfadaki örneği inceliyorum ama daha başta takıldım.
1) http://doc.qt.io/qt-5/qtnetwork-network-chat-connection-cp… bu sayfada bulunan Connection::sendMessage(...) üye fonksiyonu neden içerisinde QByteArray barındırmak zorunda? Direk QString olarak niye göndermiyoruz mesajı?

2) Yine 1. sorunun linkindeki sayfada Connection::sendGreetingMessage() bu üye fonksiyon neden gerekli? Zaten mesaj göndermiyor muyuz sendMessage() ile?

3) Ayrıca bu sayfadaki http://doc.qt.io/qt-5/qtnetwork-network-chat-client-cpp.html Client::sendMessage(const QString &message) bu mesaj gönderme ne alaka? Zaten connection.cpp dosyasında yazmadık mı o üye fonksiyonu?

4) Son olarak http://doc.qt.io/qt-5/qtnetwork-network-chat-server-cpp.html bu sayfadaki Server::incomingConnection(qintptr socketDescriptor) bu üye fonksiyonun Türkçe karşılığı gelenBağlantı şeklinde fakat bu ne demek? Yani uygulama içinde ne işe yarıyor? Ayrıca qintptr socketDescriptor parametresine neden gerek var?

Umarım sorularımla sizi sıkmamışımdır. Eğer öyleyse affola. Malum soket programlamayı net anlatan bir kaynak bulamadım. Terimlerin çoğunu teorik olarak biliyorum. O da uygulama geliştitirken yüzeysel kalıyor.

Teşekkürler!
acehreli (Moderatör) #10
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
İbrahim:
Direk QString olarak niye göndermiyoruz mesajı?

Soket düzeyine indiğimizde dizgi kavramının daha altındayız. Soketler resim gibi metin olmayan bilgi de gönderebildiklerinden baytlardan oluşan bilgi gönderirler. QString'in belgesinde ise Unicode dizgi olduğu yazılı. Dizgilerin kodlanmaları (UTF-8 mi, başka bir şey mi, vs.) gibi kavramlar bu düzeyde bulunmaz.

Connection::sendGreetingMessage() bu üye fonksiyon neden gerekli?

Tahmin ediyorum: Sanırım o sunucu ile istemci arasındaki bağlantı protokolünün parçası, kullanıcının gönderdiği sohbetin parçası değil. Bir anlamda, istemci sunucuya "merhaba, bağlanmak istiyorum" diyor; sunucu da ona "olur kardeş" diyor. :) İnsanların mesajları ise sendMessage() ile gönderiliyor.

Zaten connection.cpp dosyasında yazmadık mı o üye fonksiyonu?

Connection ile Client farklı sınıf türleri; üye işlevleri farklı. Olabildiğinde tek kod yazar ve paylaştırırız ama buradaki sendMessage'lar farklı. Örneğin, birisi değer döndürüyor ama öbürü döndürmüyor. Tasarlayanlar nedense öyle düşünmüşler. :)

bu üye fonksiyonun Türkçe karşılığı gelenBağlantı şeklinde fakat bu ne demek?

Sanırım istemci bağlandığında "şu soketten bağlantı geldi" anlamında çağrılıyor.

Ayrıca qintptr socketDescriptor parametresine neden gerek var?

Adına bakarak "soket belirticisi". Gelen bağlantı hakkında bilgi taşıyordur.

Umarım sorularımla sizi sıkmamışımdır.

Tabii ki değil ama ben bu örneğin soket programlanın kendisini öğrenmeye yarayacağını sanmıyorum. İşin içinde Qt ne yapıyor? Diyalog pencerelerine filan ne gerek var? :) Ben olsam soket programlamadan başka bir şey içermeyen bir örneğe bakardım:

  • Sunucu beklemeye başlasın

  • İstemci bağlansın

  • İstemci "merhaba" desin

  • Sunucu da "merhaba" desin

  • Sonlansınlar

Eğer bu kadar alt düzeyi bilmek gerekmiyorsa (ben olsam uygulamada o kadar alta inmem ve std.socket gibi üst düzey bir modülü kullanırım) o zaman üst düzey modüllere bakmak gerek.

Malum soket programlamayı net anlatan bir kaynak bulamadım.

Daha önce yazdığım soket örneğindeki ilgisiz kodları çıkarttım. (Linux ortamında çalışıyor.) main çok basit. Geri kalanında ya Sunucu iş görüyor ya da İstemci.

Sunucu'nun kurucusu bind ve listen yapıyor. Böylece soket hazır hale geliyor. Sonra hizmetEt içinde 'accept' ile bağlantı bekliyor.

İstemci'nin kurucusu ise 'connect' ile bağlanıyor ve send ile mesaj gönderiyor. İstemci "bitti" mesajı gönderdiğinde bağlantıyı kesiyorlar.
import std.stdio;
import std.socket;
import std.getopt;
import std.string;
 
/* 'Unix domain socket'ler dosya sisteminde dosya olarak
 * beliriyorlarmış. Anladığım kadarıyla kullanıcının bu dosyayla doğrudan bir
 * işi olmuyor.
 *
 * Dosya isminin ilk karakterinin '\0' olması da en azından dosya isim
 * çakışmalarını önlüyormuş. Hatta, böyle isimdeki dosyaların remove() ile
 * silinmeleri de gerekmiyormuş.
 */
enum soketİsmi = "\0/tmp/deneme_soketi";
 
int main(string[] parametreler)
{
    // Sunucu rolünde mi olalım istemci mi
    enum Rol { sunucu, istemci }
    Rol rol;
 
    try {
        // Programın ismi dahil, iki parametre olmalı
        enforce(parametreler.length == 2);
 
        // Rol olamayacak değer geldiğinde hata atar
        getopt(parametreler, "rol", &rol);
 
    } catch {
        stderr.writefln("Kullanım:\n    %s --rol={sunucu|istemci}",
                        parametreler[0]);
        return 1;
    }
 
    final switch (rol) {
    case Rol.sunucu:  sunucuOl(soketİsmi); break;
    case Rol.istemci: istemciOl(soketİsmi); break;
    }
 
    return 0;
}
 
void sunucuOl(string soketİsmi)
{
    auto sunucu = Sunucu(soketİsmi);
    sunucu.hizmetEt();
}
 
void istemciOl(string soketİsmi)
{
    auto istemci = İstemci(soketİsmi);
    istemci.iste();
}
 
struct Sunucu
{
    Socket dinleyici;
 
    this(string soketİsmi)
    {
        // Önce bağlantıları karşılayacak olan soketi hazırlıyoruz
        dinleyici = new Socket(AddressFamily.UNIX, SocketType.STREAM);
        auto adres = new UnixAddress(soketİsmi);
 
        dinleyici.bind(adres);
        dinleyici.listen(1);
    }
 
    ~this()
    {
        dinleyici.shutdown(SocketShutdown.BOTH);
        dinleyici.close();
        destroy(dinleyici);
        // Dosyanın silinmesinin gerekip gerekmediğinden aslında emin değilim:
        remove(soketİsmi.toStringz);
    }
 
    /* Sonsuz döngüde istemci bekler ve ona yanıt verir. */
    void hizmetEt()
    {
        while (true) {
            // İstemci bekliyoruz
            writeln("Bekliyorum...");
 
            // Şimdi o sokette bağlantı kabul ediyoruz.
            Socket istemci = dinleyici.accept();
 
            // Bu istemciyle işimiz bittiğinde gereken temizlik işlemi:
            scope (exit) destroy(istemci);
 
            writeln("Bir istemci bağlandı.");
 
            // İstemci gidene kadar istemci döngüsündeyiz
            while (istemci.isAlive) {
                string istek = istemci.tekParçaOlarakOku();
 
                string yanıt = format("(%s)", istek);
                istemci.send(yanıt);
 
                if (istek == "bitti") {
                    break;
                }
            }
 
            writeln("Bu istemciyle işim bitti.");
        }
    }
}
 
/* Socket.receive'in aksine, okunan parçaları birleştirir ve tek string olarak
 * döndürür. */
string tekParçaOlarakOku(Socket soket)
{
    string okunan;
 
    // Okunan veriyi parça parça bu belleğe alacağız
    ubyte[1000] parça;
    bool bütünVeriOkundu_mu = false;
 
    while (!bütünVeriOkundu_mu) {
        const adet = soket.receive(parça);
 
        if (adet == Socket.ERROR) {
            stderr.writeln("OKUMA HATASI");
            break;
        }
 
        okunan ~= parça[0..adet];
 
        bütünVeriOkundu_mu = (adet < parça.length);
    }
 
    return okunan;
}
 
struct İstemci
{
    Socket soket;
 
    this(string soketİsmi)
    {
        soket = new Socket(AddressFamily.UNIX, SocketType.STREAM);
        soket.connect(new UnixAddress(soketİsmi));
    }
 
    ~this()
    {
        soket.shutdown(SocketShutdown.BOTH);
        soket.close();
        destroy(soket);
    }
 
    void iste()
    {
        while (true) {
            write("Sunucuya gönderilecek mesajı yazın: ");
            const mesaj = chomp(readln());
            const adet = soket.send(mesaj);
            writefln("%s bayt gönderdim", adet);
 
            string yanıt = soket.tekParçaOlarakOku();
            writefln("Yanıt aldım: %s", yanıt);
 
            if (mesaj == "bitti") {
                break;
            }
        }
    }
}
Ali
Bu mesaj acehreli tarafından değiştirildi; zaman: 2015-10-22, 01:47.
İbrahim #11
Üye Eki 2015 tarihinden beri · 156 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Merhaba Ali Hocam, verdiğiniz D örneğini inceliyorum (C++'a benziyor zaten). Teşekkürler.

... Soketler resim gibi metin olmayan bilgi de gönderebildiklerinden baytlardan oluşan bilgi gönderirler. ...

Peki bu QByteArray bir resmi nasıl tutuyor (veya bir videoyu)?

... ben bu örneğin soket programlanın kendisini öğrenmeye yarayacağını sanmıyorum. İşin içinde Qt ne yapıyor? Diyalog pencerelerine filan ne gerek var? :) Ben olsam soket programlamadan başka bir şey içermeyen bir örneğe bakardım:

Qt - C++ tercih etmemin sebebi bir kere Qt'un cross platform olması. 2. nedenim ise mobil native uygulama geliştirirken Qt tüm mobil platformlara adapte olabiliyor. Soket programlamayı Qt'da öğreneyim bari dedim ama olmadı :) C++'ın sys/socket.h adlı bir dosyası varmış onu da inceleyeyim, belki o daha az karmaşıktır.

Teşekkürler!
acehreli (Moderatör) #12
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
İbrahim:
QByteArray bir resmi nasıl tutuyor (veya bir videoyu)?

Adından bir dizi bayt olduğu anlaşılıyor.

Bellekte, diskte, ve başka her yerde bilginin bitlerle ifade edildiğini biliyorsun. Sekiz bit bir araya gelince bayt oluyor ve zaten her şey bir dizi bayt olarak ifade ediliyor. Dolayısıyla, QByteArray veya eşdeğerleri zaten en doğal türlerdir. :)

Ali
İbrahim #13
Üye Eki 2015 tarihinden beri · 156 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Cevap için teşekkür ederim.

Sorun olmazsa bir soru daha sormak istiyorum: Acaba Whatsapp, Skype vb. uygulamaların chat sisteminde güvenlik haricinde bizim bu yaptığımız chat örnek uygulamalarından farkı var mı? Yani güvenliği saymazsak bizim bu chat sisteminden daha mı hızlı çalışıyorlar? Eğer hız vb. farklar varsa bunlar nelerdir ve nasıl yapıyorlar?

Umarım anlatabilmişimdir. Teşekkürler!
acehreli (Moderatör) #14
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Hayır, hız farkı yok.

Ali
İbrahim #15
Üye Eki 2015 tarihinden beri · 156 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Teşekkürler.

Şu anda http://www.boost.org/doc/libs/1_59_0/doc/html/boost_asio.h… Boost Asio kütüphanesini buldum. Çok daha kolay geldi ve oop yapısında. Bununla devam edeceğim. Bu kütüphane hakkındaki görüşlerinizi alabilir miyim?
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Sayfa:  1  2  sonraki 
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2017-11-19, 05:57:35 (UTC -08:00)