Haftalık C++ 22 – Qt Kod Parçaları – I

Arkadaşlar bugün sizler ile QT ile ilgili bir kaç kod parçası paylaşmak istiyorum. Bundan önce bir kaç yazımda, soket programlama ve geliştirdiğim bir takım kabiliyetler ile ilgili sizlerle bazı paylaşımlarda bulunmuştum. Bu yazılarımda, Qt ve C++ kullanarak TCP istemci ve sunucu soketlerini nasıl oluşturabileceğimize, kod üzerinden ve tasarımcıyı kullanarak nasıl grafiksel kullanıcı arayüzüne sahip uygulamalar geliştirebileceğimize bakmıştık.
O yazılarımdan sonra, bütün bu yazılarımda sizler ile paylaştığım kabiliyetleri (ve biraz daha fazlasını) içerisinde barındıracak olan Socket Box uygulamam üzerinde çalışmaya başladım. Bu uygulama arka planda, C++ tabanlı NetworkLibrary kullansa da, grafiksel kullanıcı arayüzlerini QML kullanarak geliştiriyorum. Bu sayede hem kolay bir şekilde çoklu platform desteği hem de iş mantıkları ile grafiksel kullanıcı arayüzleri arasında bağımsızlık oldukça kolay bir şekilde sağlanabiliyor (bu arada QML ile ilgili, başlangıç için SSL, Qt5 Cadaques yazıma muhakkak bir göz atmanızı tavsiye ediyorum).

Bu yazımda sizler ile, bu uygulamayı geliştirirken kullandığım, sizlere de faydalı olacak ve vakit kazandıracak bir takım kod parçalarını paylaşmak istiyorum. Bir süre bu ve benzeri bir takım paylaşımları çok uzun olmayan yazılar ile sizlerle paylaşacağım.

Evet pek de kısa olmayan 🙂 bir girişten sonra, bu yazı kapsamında sizler ile paylaşacağım ilk kod parçasına  geçebiliriz.

Metin Dönüşümleri, Hexadecimal Veri Gösterimi

QT ile yazılım geliştirirken en çok karşılaşacağınız sınıflardan birisi de QString sınıfıdır. Bu sınıf bünyesinde bir çok API barındırmakta, metin dönüşümleri ve C++ std::string benzeri bir çok kabiliyeti de sunmaktadır. Bunun ile birlikte bir çok QT kütüphanesinde de bu sınıf kullanılmakta. Bu sınıf kullanırken bir noktada sprintf benzeri bir API’ye ihtiyacınız olabilir bu durumda ne yapıcaksınız? Konu Qt olunca, elbette birden fazla seçenek mevcut.

Bunlardan ilki sprintf API’si kullanmak 🙂 Bu şekilde elde ettiğiniz metni QString sınıfına geçirebilirsiniz. Bu yöntem pek hoşunuza gitmedi ise diğer yöntemlere bakalım.

Bir diğer yöntem, yukarıdakine benzer olarak QString tarafından sunulan asprintf() API’sini kullanmak. İsminden de anlaşılacağı üzere, sprintf API’sinin arayüzünü sunan ve ondan kopamayanlar için bu API sunulmakta. Bu API statik bir metot olarak sunulmakta, fakat QT’nin kendisi tarafından pek önerilmemekte.

Yukarıdaki iki yöntem yerine arg() ve QTextStream seçeneklerini değerlendirmenizi beklemekte QT. Bunlar arasından arg() API’sine bir göz atacağız. Hemen bir iki örnek ile buna bakalım:

Yukarıdaki örnek kod parçasından da anlayacağınız üzere, bu API daha okunabilir ve QT tarafından tercih edilmekte. Ayrıca diğer bazı programlama dillerinde de benzer kullanımlar mevcut. Bunun yanında bu kullanımın bize sunduğu bir kaç avantaj da mevcut. Bunlardan ilki, geçirilen parametrelerin sıralarını değiştirmeden, elde edilecek metnin içeriğini ve kullanım yerlerini değiştirebilirsiniz. Ayrıca kullanılan argüman tiplerini de yine benzer şekilde formatlama metnini değiştirmeden değiştirebilirsiniz.

Bunlar yanında, sayısal değerleri QString’e çevirmek için statik number() API’lerini, tesi dönüşümler için ise toInt, toDouble ve benzeri varyasyonlarını kullanabilirsiniz.

Bu noktada ihtiyaç duyacağınız ve sıklıkla kullanacağınız dönüşüm de toStdString() ve varyasyonları olacak. Bu API’leri de std::string ve std::wstring dönüşümleri için kullanabilirsiniz.

Elinizde soket üzerinden ya da “binary” bir dosyadan okuduğunuz verilerin tutulduğu QByteArray var ve bunun içeriğini hexadecimal görmek istiyorsunuz neyi kullanacaksınız. Hemen gösterelim:

Peki ya tarih ve saati nasıl alacağım:

TCP sunucu soketinize bir istemci bağlandı. İstemcinin IP adresini öğrenmek istiyorsunuz (yerel makineninkini nasıl öğreneceğimiz birazdan 😉 ), içinden gelen sese kulak verdin ve toString() API’sini kullandın ama IP metni IPv6 formatında ve fazladan “:” karakterleri var ne yapacaksın. Aşağıdaki metot işini görecektir:

Bu kadar metin dönüşümlerine ilişkin kod parçası şimdilik yeterli, şimdi biraz daha eğlenceli kod parçalarına göz atalım.

IP ve MAC Adresini Öğrenme

Qt de soket programlama ile uğraşıyorsanız, bir noktada makinenizin IP adresini ve kullandığınız aygıtların MAC adreslerini öğrenme ihtiyacı hasıl olmuş olabilir (benim için en azından, yeni geliştirdiğim uygulama için gerekti). İşte bu başlık altında bunlara bakacağız.

Bu bağlamda geliştireceğimiz üç ana kabiliyet mevcut. Bunlar:

  • Cihazımıza ilişkin özel IP adresi (private IP Address) belirleme:
    • Bu adres genel olarak yerel ağ içerisinde (LAN) haberleşmek için kullanılır ve kapsamı yereldir,
    • Windows komut satırında “ipconfig” komut ile görüntülenen “IPv4 Address” si mevcut cihazınızın özel IP adresidir,
    • Basit ağ API’leri kullanılarak elde edilebilir.
  • Cihazımıza ilişkin umumi IP adresi (public IP Address) belirleme:
    • Bu adres ağ dışında, internet üzerindeki diğer makineler ile haberleşmek için kullanılır ve kapsam globaldir,
    • Internet ile ilgili servisleri almak için kullanılan adrestir,
    • Internet servis sağlayıcıları tarafından yönetilir ve genelde ücretlidir,
    • Umumi IP adresinizi “what is my ip” gibi servisleri kullanarak öğrenebilirsiniz ya da router’ınızın yönetim sayfasından.
  • Cihazımıza ilişkin MAC adresini belirleme:
    • MAC adresi, ağa bağlı olan bir cihaza iliştirilmiş, üreticiler tarafından atanan, eşsiz tanıtıcıdır. Bu adresler, altı haneden oluşurlar ve üreticiyi temsil ederler. Örnek adresler genelde şu şekilde olur: 68:7F:74:12:34:56,
    • Ağ ile ilgili bir bilgi içermez.

Şimdi bu üç kabiliyeti içerisinde barındıran bir sınıf geliştireceğiz. Bu sınıf sayesinde bu bilgileri elde etmenin yanı sıra, bir sonraki yazımızda da göreceğimiz üzere QML tarafında da kullanılabileceğiz (elbette ufak tefek bir kaç makyajdan sonra) bir kabiliyet sınıfı oluşturmuş olacağız.

Öncelikli olarak başlık dosyamızı ve sınıfımızı yazalım:

Evet, artık bu metotların içerisini doldurmanın vakti geldi. Aşağıda, ilgili kod parçalarını bulabilirsiniz:

Burada öncelikle umumi IP adresini elde etmek için izlediğimiz yönteme dair bir iki kelam edeyim. Daha önce de bahsettiğim gibi, bunu öğrenmek için çeşitli web servislerini kullanabilirsiniz. Burada da ben http://ipify.org adresini kullandım. Bu servis ile bir çok programlama dilini kullanarak IP adresini sorgulayabilirsiniz.

İlgili istek metnini oluşturup  QNetworkAccessManager nesnesi aracılığı ile bu servise gönderiyoruz. Bunun cevabını ayrı bir slot aracılığı ile alacağız. Gelen cevap JSON formatında ve aşağıdaki gibi olacaktır. Burada da yine sevgili QT’nin JSON kabiliyetlerini kullanarak aranan adresimizi elde edebiliyoruz.

MAC adreslerini sorgulamak için ise QNetworkInterface sınıfını kullanıyoruz. Bu sınıf aracılığı ile cihazımıza bağlı ağ aygıtlarına ilişkin bilgileri sorgulayabiliyoruz. Burada ihtiyacınıza göre QNetworkInterface::InterfaceFlag ve QNetworkInterface::InterfaceType değerlerini kontrol etmeniz gerekebilir. Aşağıda ilgili API sayfasından, kullanma ihtimaliniz yüksek olanları buraya ekliyorum. Tam liste için, verdiğim bağlantıya bakabilirsiniz.

Bu arada, özel IP adresimizi getPrivateIPAddress() metodu aracılığı ile bulmak için de bu değerleri kullandığımızı görebilirsiniz.

QNetworkInterface::InterfaceFlag değerleri:

Constant Value Description
QNetworkInterface::IsUp 0x1 the network interface is active
QNetworkInterface::IsRunning 0x2 the network interface has resources allocated
QNetworkInterface::IsLoopBack 0x8 the network interface is a loopback interface: that is, it’s a virtual interface whose destination is the host computer itself

QNetworkInterface::InterfaceType değerleri:

Constant Value Description
QNetworkInterface::Unknown 0 The interface type could not be determined or is not one of the other listed types.
QNetworkInterface::Loopback 1 The virtual loopback interface, which is assigned the loopback IP addresses (127.0.0.1, ::1).
QNetworkInterface::Virtual 2 A type of interface determined to be virtual, but not any of the other possible types. For example, tunnel interfaces are (currently) detected as virtual ones.
QNetworkInterface::Ethernet 3 IEEE 802.3 Ethernet interfaces, though on many systems other types of IEEE 802 interfaces may also be detected as Ethernet (especially Wi-Fi).
QNetworkInterface::Wifi 8 IEEE 802.11 Wi-Fi interfaces. Note that on some systems, QNetworkInterface may be unable to distinguish regular Ethernet from Wi-Fi and will not return this enum value.

 

Şimdi de, bu sınıfın örnek kullanımına da bir göz atalım:

Bu kodu çalıştırdığınızda aşağıdaki gibi bir çıktı alacaksınız:

QT Creator Klavye Kısa Yolları

Evet arkadaşlar bir önceki yazımda Visual Studio kullanarak QT uygulamalarını geliştiriyordum. Bir süredir, özellikli çoklu platformlar için geliştirdiğim QT uygulamaları için, QT creator kullanmaya başladım. Her ne kadar Visual Studio kadar olmasa da QT yazılım geliştirme için gayet yeterli. Bu anlamda, ilk baktığım şeylerden birisi de klavye kısa yolları oldu. Aşağıda başka bir kaynaktan bulduğum, kısa ve öz bir kısa yol listesi bulabilirsiniz. Bir kısım kısa yolların, Visual Studio ile aynı olduğunu, dikkatli takipçilerim hemen fark edecektir.

Tam liste için https://doc.qt.io/qtcreator/creator-keyboard-shortcuts.html adresine bir göz atmanızda fayda var.

 

Evet arkadaşlar bir yazımın daha sonuna geldik. Bundan sonra QT ve QML entegrasyonu konusunda değinmeyi planlıyorum. Ayrıca ağ programlama çalışmalarınız için çok faydalı olacağını düşündüğüm bir yazılımımı da yakında sayfamdan duyuracağım.

Ben yazılımperver, bir sonraki görüşmemize kadar kendinize iyi bakın, bol kodlu günler 😀

Bir cevap yazın

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

Bu site, istenmeyenleri azaltmak için Akismet kullanıyor. Yorum verilerinizin nasıl işlendiği hakkında daha fazla bilgi edinin.