Selasa, 17 Desember 2013

SFML Network dengan Thread untuk client server [bagian 3]

sekarang mari kita lihat bagian kode berikut:

if(config.port==0) {
        Socket.bind(sf::Socket::AnyPort);
        Port = Socket.getLocalPort();
    } else {
        Port = config.port;
        if(Socket.bind(config.port) != sf::Socket::Done) {
            std::wstringstream ss; ss << L"{RDError:} Could not bind to port {YD" << config.port << L"}.";
            writeToLog(ss.str());
            return false;
        }
    }


saya translasikan kedalam bahasa indonesia menjadi begini:


jika (config.port adalah 0) maka jalankan
{
  Socket.bind(dengan parameter yang diambil dari object sf::Socket::AnyPort);

  dan Variable Port diisi dengan nilai dari Socket.getLocalPort();
}
jika tidak demikian maka jalankan
{
  variable Port diisi dengan nilai config.port;
  jika (Socket.bind(dengan parameter dari config.port) tidak sama dengan nilai sf::Socket::Done) maka jalankan
  {
    definisikan std::wstringstream sebagai ss;
    ss diisi dengan "{RDError:} Could not bind to port {YD" ditambah lagi dengan nilai dari config.port;
    jalankan writeToLog(dengan nilai ss.str());
    kembalian adalah salah;
  }
}


dari kode diatas dapat dijelaskan bahwa pada awalnya Server.init() akan memeriksa nilai didalam object config.port, jika nilainya 0 maka perintah socket.bind akan dijalankan dengan nilai port yang diambil secara acak oleh object sf::Socket::AnyPort. hal ini tentunya tidak akan pernah terjadi sehubungan kita telah menetapkan nilai bukan 0 melainkan 8888 untuk config.port pada main.cpp. jadi yang dieksekusi adalah kemungkinan kedua.


pada kemungkinan kedua terlihat bagaimana variable Port diisi dengan nilai config.port dan selanjutnya dilakukan kembali pemanggilan sekaligus pengecekan terhadap Socket.bind dengan menggunakan nilai dari config.port, jika status pemanggilan Socket.bind tersebut tidak Done maka ss akan diisi dengan "{RDError:} Could not bind to port {YD" ditambah lagi dengan nilai dari config.port, pesan tersebut akan ditulis ke file.log dan program akan memberi nilai kembalian false kepada pemanggilnya - main.cpp yang mana akan menghentikan program untuk berlanjut.


nah jika Socket.bind sukses maka kode berikutnya adalah:


    AccepterThread = new sf::Thread(&Server::runAccepter);
    MainThread = new sf::Thread(&Server::run);
    MainThread->launch();
    PacketQueueThread = new sf::Thread(&Server::handlePacketQueue);
    PacketQueueThread->launch();
    return true;


definisikan AccepterThread sebagai clone dari sf::Thread(dan registrasikan &Server::runAccepter sebagai bagian modul didalam sf::thread);


definisikan MainThread sebagai clone dari sf::thread(dan registrasikan &Server::runsebagai bagian modul didalam sf::thread);
panggil fungsi launch() yang merupakan member dari MainThread;
definisi seperti diatas dilakukan juga terhadap PacketQueueThread. kelima pendefinisian ini bisa dilakukan karena adanya: sf::Thread * Server::AccepterThread = 0; sf::Thread * Server::MainThread = 0; dan sf::Thread * Server::PacketQueueThread = 0; pada baris awal code server.cpp.


dengan dipanggilnya MainThread->launch(); dan PacketQueueThread->launch(); maka server::init sudah running dan memberikan nilai kembalian true kepada int main(...) di main.cpp. proses akan dikembalikan kepada int main(...).


namun mari kita lihat bagian ini: MainThread = new sf::Thread(&Server::run); MainThread->launch(); ketika MainThread->launch() dipanggil, maka sf::Thread akan mengeksekusi &Server::run dan berikut ini adalah kode dari fungsi &Server::run:


void Server::run() {
    writeToLog(L"Main Network Thread started.");
    sf::Clock clock;
    while(Run) {
        if(!isFull() && !Listening) {
            Listening = true;
            AccepterThread->launch();
        }
        sf::Packet packet; sf::IpAddress ip; sf::Uint16 port;
        if(Socket.receive(packet, ip, port) == sf::Socket::Done) {
            if(handleUDPPacket(packet, ip, port)) {
                //Success
            } else {
                std::wstringstream ss; ss << L"Packet error on {YDUDP Socket}.";
                writeToLog(ss.str());
            }}}} // untuk memperpendek baris kode

fungsi writeToLog dipanggil untuk menulis kata "Main Network Threa started" di layar. fungsi writeToLog adalah fungsi yang terdapat di dalam ui.cpp yang dalam hal ini tidak perlu dibahas dalu. kemudian memanggil fungsi sf::Clock melalui inheritnya dengan nama clock.
loop dilakukan selama nilai kembalian Run adalah true, Run sendiri merupakan fungsi private dari  class Server sendiri yang didefinisikan diawal code server.cpp:
bool Server::Run = true;
 

dan merujuk langsung pada definisi symbol yang terdapat di file server.hpp yaitu:
static bool Run;

proses yang di-loop adalah:
1. if(!isFull() && !Listening) {Listening = true; AccepterThread->launch();} --jika nilai kembalian fingsi isFull() tidak true dan nilai Listening juga tidak true, maka jalankan {Listening diisi nilai true; eksekusi AccepterThread->launch();}
jadi selama proses loop terus berlangsung, maka nilai Listening akan selalu dibuat true dan fungsi AccepterThread->launch(); selalu dijalankan.


2. sf::Packet packet; sf::IpAddress ip; sf::Uint16 port;
Ini adalah deklarasi atas sf::packet sebagai packet; sf::IpAddress sebagai ip; dan sf::Uint16 sebagai port;


3. if(Socket.receive(packet, ip, port) == sf::Socket::Done) {if(handleUDPPacket(packet, ip, port)) {//Success} else {std::wstringstream ss; ss << L"Packet error on {YDUDP Socket}.";    writeToLog(ss.str());}}


jika (fungsi Socket.receive dipanggil (dengan parameter:packet, ip, dan port) memberikan nilai kembalian sama dengan nilai kembalian dari sf::Socket::Done) maka jalankan proses berikut:
{
jika (fungsi handleUDPPacket dipanggil (dengan parameter:packet,ip, dan port) menghasilkan nilai kembalian true) maka jalankan {abaikan saja..} namun jika tidak demikian maka jalankan {deklarasikan std::wstringstream sebagai ss; isi ss dengan kata: "Packet error on {YDUDP Socket}."; jalankan fungsi writeToLog(dengan parameter adalah nilai kembalian dari fungsi ss.str());}
}
...tunggu lanjutannya...

Tidak ada komentar:

Posting Komentar