Metin2 P2P Bağlantısını Kullanarak Web Sitesine Oyundan Anlık Veri Gönderip Almak

Whistle

Ruhsuz :/
Kurucu
Geliştirici
Yardımsever Üye
Mesaj
11.941
Çözümler
567
Beğeni
13.661
Puan
5.915
Ticaret Puanı
2
Merhaba arkadaşlar,
P2P dediğimiz zaman bir çoğumuz korkabilir. Bu zıkkım yüzünden başınıza gelmeyen kalmamıştır lakin ne işe yaradığını öğrendiğinizde kesinlikle çok seveceksiniz. <3

Öncelikle Nedur Bu P2P?
Peer-to-peer
ya da P2P olarak tanımlanır. Peer eş, denk demektir. İki veya daha fazla istemci arasında veri paylaşmak için kullanılan bir ağ protokolüdür.

Eşler, sunucuları veya sabit bilgisayarlar tarafından merkezi koordinasyon ihtiyacı olmadan, işlemci gücü, disk depolama veya ağ bant genişliği gibi kendi kaynaklarının bir kısmını, doğrudan diğer ağ katılımcıları için kullanılabilir yapabilir. Sadece sunucuların tedarikçi ve istemcilerin tüketici olduğu geleneksel istemci-sunucu modelinin aksine, eşler, hem tedarikçi hem de tüketicidir.

Metin2 Neden P2P'ye İhtiyaç Duyar?
Kanallar arası iletişimi sağlamak, anlık veri alıp göndermek için kullanılır.

Web Sitemiz İle Oyuna P2P İle Bağlanmak Mümkün Mü?
Evet mümkün fakat güvenlik önlemlerini çok iyi şekilde almanız gerekmektedir. P2P kodları ile serverinizi bir yönetici gibi yönetebilir..

Web Sitesinde P2P Bağlantısını Kullanarak Verileri Almak Mı Yoksa Veritabanı Kullanarak Almak Mı Karlı?
Bu çok az bilinen bir konudur fakat bu zamana kadar edindiğin tecrübelerde. Oyundaki her işlem anlık olarak veritabanına kayıt edilmez. Genelde fileslerde her 30dk'da bir oyun veritabanına yazılır. Bu süreyi düşürebilirsiniz.
Reboot atarken item kaybıda bu yüzden yaşanmaktadır.

Online sayacından örnek vermek gerekirse. Her bir karakteri alıp onun en son girdiği saate bakıp hepsini saydırmanız gereken bir sql cümlesi yazmanız gereklidir. Buda tabikide belli bir işlem gücü demektir. Bu veriler ise oyun ile eş bir şekilde çalışmaz. Oyunda veritabanı yedeğini ne kadar süre belirlediyseniz 30dk ise 30dk önce olanları gösterir..

Kısacası P2P kullanarak anlık olarak oyunda etkileşimde bulunabilir, veriler alabilirsiniz ve daha az kaynak tüketirsiniz.

Web Sitemizde P2P Yardımı İle Hangi İşlemleri Yaparız?
  • Anlık online sayacı yapabilirsiniz. Her bayrak için ayrı ayrı'da alabilirsiniz.
  • Oyuncuları dc atabilirsiniz.
  • GM kodlarını kullanabilirsiniz. (Panelden birisine gold gönderecekseniz p2p ile anlık gönderebilirsiniz. Veritabanı ile bu mümkün değildir! Karakterin 30dk oyunda olmaması gerekli.)
  • Anlık olarak item gönderebilirsiniz.
  • Ban, chat banı atabilrisiniz.
  • Serveri bakım moduna alabilirsiniz.
  • Eventleri açıp kapatabilirsiniz. (Panel üzerinden otomatik event başlatıcı ve bitirici sistem yapabilirsiniz.)
  • Panel üzerinden oyuna notlar gönderebilirsiniz.
Gördüğünüz gibi yapılacak çok şey var. :)

Tabi ben size burada her özelliği tek tek nasıl yazacağınızı anlatmayacağım. :(

P2P komutlarını öğrenmek için ilk önce serverinizin server kaynak kodunda;
game/src/input.cpp açıp;
C++:
Genişlet Daralt Kopyala
int CInputHandshake::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)
bu satırı bulmanız.
Bunun altında "USER_COUNT" gibi komutlar var.

Örnek PHP komutu;
PHP:
Genişlet Daralt Kopyala
<?php
/**
* Created by PhpStorm.
* User: Whistle | MMO Tutkunları | mmotutkunlari.com
* Date: 1/6/2017
* Time: 9:47 PM
*/

/**
* Servere p2p ile bağlantı göndermek için kullanılır.
*
* @param $yazi
* @param string $tip
* @param int $port
* @return array|string
*/
function P2PSendServer($yazi, $tip = "NOTICE", $port = 13000)
{
        // Metin2 serverin IP ve ADMINPAGE_PASSWORD
    $serverIp = "192.168.1.105"; $sifre = "buraya p2p adminpage_password gelecek!";

    // CREATE
    $socket = socket_create (AF_INET, SOCK_STREAM, SOL_TCP);

    if ($socket < 0)
    {
        echo "\n Gecersiz socket...\n";

        exit;
    }

    $sonuc = socket_connect ($socket, $serverIp, $port);

    if ($sonuc < 0)
        echo "\n Bağlantı hatası. Hata : ".socket_strerror($sonuc)."\n";

    if($tip == "USER_COUNT")
        $sorgu = "\x40".$tip."\x0A";
    else
    {
        $sorgu2 = "\x40".$sifre."\x0A";
        $sorguBoyut2 = strlen($sorgu2);
        $sorguSonuc2 = socket_write($socket, $sorgu2, $sorguBoyut2);
        socket_recv($socket, $sonuc2, 256, 0);
        $sorgu = "\x40".$tip." ".$yazi."\x0A";
    }

    $sorguBoyut = strlen($sorgu);
    $sorguSonuc = socket_write($socket, $sorgu, $sorguBoyut);

    if ($sorguSonuc < 0)
        echo "Hata: ".socket_strerror($sorguSonuc)."\n";
    else
        $sonuc1 = socket_recv($socket, $sonuc2, 256, 0);


    if ($tip == "USER_COUNT")
    {
       $say = trim($sonuc2);
        $say = explode(' ', $say);
        //$say[0] = Kanaldaki toplam online
        //$say[1] = Kırmızı bayrak toplam online
        //$say[2] = Sarı bayrak toplam online
        //$say[3] = Mavi bayrak toplam online
        //$say[4] = Çekirdek toplam online
        return $say;
    }
    else
    {
        return "$sonuc2\n";
    }


    // P2P Baglantı kapat.
    socket_close($socket);
}


$say1 = P2PSendServer("", "USER_COUNT", 14000); //CH1


?>
 
Son düzenleme:
Bu konudaki işlemi yapabilmek için bir sunucu kiralamak gerekiyor mu yoksa evdeki sunucumuzdan bu işlemi gerçekleştirebiliyor muyuz. Websitem de local sunucumda local laptoptan deniyorum. Sitede online sayısını yazdırdığımda çıktı olarak anlamsız karakterler veriyor.

SS:
ss.webp


yardımcı olursanız sevinirim.
 
Localdeki makinaya ssh ile bağlanabiliyorsanız web sitesi de bağlanır. Oyuna girip tekrar çalıştırmayı deneyin.
 
Bu konudaki işlemi yapabilmek için bir sunucu kiralamak gerekiyor mu yoksa evdeki sunucumuzdan bu işlemi gerçekleştirebiliyor muyuz. Websitem de local sunucumda local laptoptan deniyorum. Sitede online sayısını yazdırdığımda çıktı olarak anlamsız karakterler veriyor.

SS:
1313 eklentisini görüntüle

yardımcı olursanız sevinirim.

Bende aynı sorundan müzdaribim. Ne yaparsam yaptım çözemedim. Lütfen yardımcı olun. Kaç gündür uğraşıyorum.
 
En son bir moderatör tarafından düzenlenmiş:
Local sunucuda da olur bilişim sunucusunda da olur. p2p portlarını kendi serverinize göre ayarlayın.
P2P portlarını kendi serverinize göre ayarlayın derken anlamadım hocam. 13010 p2p portu zaten nasıl bi ayarlama yapacağımızdan bahseder misiniz?

çok kişiye mesaj attım kimse geri dönüş yapmadı çok araştırma yaptım ama bi sonuç elde edemedim lütfen destek olun hocam facebooktanda yazdım size
 
En son bir moderatör tarafından düzenlenmiş:
P2P portlarını kendi serverinize göre ayarlayın derken anlamadım hocam. 13010 p2p portu zaten nasıl bi ayarlama yapacağımızdan bahseder misiniz?

çok kişiye mesaj attım kimse geri dönüş yapmadı çok araştırma yaptım ama bi sonuç elde edemedim lütfen destek olun hocam facebooktanda yazdım size
PHP:
Genişlet Daralt Kopyala
P2PSendServer("", "USER_COUNT", 14000);

Burada p2psend server fonksiyonunu çalıştıran kod var. 14000 kısmını 13010 şeklinde değiştirin.

PHP:
Genişlet Daralt Kopyala
$serverIp = "192.168.1.105"; $sifre = "buraya p2p adminpage_password gelecek!";
Buradada ip ve şifrenizi yazın.
Şifre kısmı CONFIG dosyasında bulunan admin page şifresi olacak.
 
Merhaba arkadaşlar,
P2P dediğimiz zaman bir çoğumuz korkabilir. Bu zıkkım yüzünden başınıza gelmeyen kalmamıştır lakin ne işe yaradığını öğrendiğinizde kesinlikle çok seveceksiniz. <3

Öncelikle Nedur Bu P2P?
Peer-to-peer
ya da P2P olarak tanımlanır. Peer eş, denk demektir. İki veya daha fazla istemci arasında veri paylaşmak için kullanılan bir ağ protokolüdür.

Eşler, sunucuları veya sabit bilgisayarlar tarafından merkezi koordinasyon ihtiyacı olmadan, işlemci gücü, disk depolama veya ağ bant genişliği gibi kendi kaynaklarının bir kısmını, doğrudan diğer ağ katılımcıları için kullanılabilir yapabilir. Sadece sunucuların tedarikçi ve istemcilerin tüketici olduğu geleneksel istemci-sunucu modelinin aksine, eşler, hem tedarikçi hem de tüketicidir.

Metin2 Neden P2P'ye İhtiyaç Duyar?
Kanallar arası iletişimi sağlamak, anlık veri alıp göndermek için kullanılır.

Web Sitemiz İle Oyuna P2P İle Bağlanmak Mümkün Mü?
Evet mümkün fakat güvenlik önlemlerini çok iyi şekilde almanız gerekmektedir. P2P kodları ile serverinizi bir yönetici gibi yönetebilir..

Web Sitesinde P2P Bağlantısını Kullanarak Verileri Almak Mı Yoksa Veritabanı Kullanarak Almak Mı Karlı?
Bu çok az bilinen bir konudur fakat bu zamana kadar edindiğin tecrübelerde. Oyundaki her işlem anlık olarak veritabanına kayıt edilmez. Genelde fileslerde her 30dk'da bir oyun veritabanına yazılır. Bu süreyi düşürebilirsiniz.
Reboot atarken item kaybıda bu yüzden yaşanmaktadır.

Online sayacından örnek vermek gerekirse. Her bir karakteri alıp onun en son girdiği saate bakıp hepsini saydırmanız gereken bir sql cümlesi yazmanız gereklidir. Buda tabikide belli bir işlem gücü demektir. Bu veriler ise oyun ile eş bir şekilde çalışmaz. Oyunda veritabanı yedeğini ne kadar süre belirlediyseniz 30dk ise 30dk önce olanları gösterir..

Kısacası P2P kullanarak anlık olarak oyunda etkileşimde bulunabilir, veriler alabilirsiniz ve daha az kaynak tüketirsiniz.

Web Sitemizde P2P Yardımı İle Hangi İşlemleri Yaparız?
  • Anlık online sayacı yapabilirsiniz. Her bayrak için ayrı ayrı'da alabilirsiniz.
  • Oyuncuları dc atabilirsiniz.
  • GM kodlarını kullanabilirsiniz. (Panelden birisine gold gönderecekseniz p2p ile anlık gönderebilirsiniz. Veritabanı ile bu mümkün değildir! Karakterin 30dk oyunda olmaması gerekli.)
  • Anlık olarak item gönderebilirsiniz.
  • Ban, chat banı atabilrisiniz.
  • Serveri bakım moduna alabilirsiniz.
  • Eventleri açıp kapatabilirsiniz. (Panel üzerinden otomatik event başlatıcı ve bitirici sistem yapabilirsiniz.)
  • Panel üzerinden oyuna notlar gönderebilirsiniz.
Gördüğünüz gibi yapılacak çok şey var. :)

Tabi ben size burada her özelliği tek tek nasıl yazacağınızı anlatmayacağım. :(

P2P komutlarını öğrenmek için ilk önce serverinizin server kaynak kodunda;
game/src/input.cpp açıp;
C++:
Genişlet Daralt Kopyala
int CInputHandshake::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)
bu satırı bulmanız.
Bunun altında "USER_COUNT" gibi komutlar var.

Örnek PHP komutu;
PHP:
Genişlet Daralt Kopyala
<?php
/**
* Created by PhpStorm.
* User: Whistle | MMO Tutkunları | mmotutkunlari.com
* Date: 1/6/2017
* Time: 9:47 PM
*/

/**
* Servere p2p ile bağlantı göndermek için kullanılır.
*
* @param $yazi
* @param string $tip
* @param int $port
* @return array|string
*/
function P2PSendServer($yazi, $tip = "NOTICE", $port = 13000)
{
        // Metin2 serverin IP ve ADMINPAGE_PASSWORD
    $serverIp = "192.168.1.105"; $sifre = "buraya p2p adminpage_password gelecek!";

    // CREATE
    $socket = socket_create (AF_INET, SOCK_STREAM, SOL_TCP);

    if ($socket < 0)
    {
        echo "\n Gecersiz socket...\n";

        exit;
    }

    $sonuc = socket_connect ($socket, $serverIp, $port);

    if ($sonuc < 0)
        echo "\n Bağlantı hatası. Hata : ".socket_strerror($sonuc)."\n";

    if($tip == "USER_COUNT")
        $sorgu = "\x40".$tip."\x0A";
    else
    {
        $sorgu2 = "\x40".$sifre."\x0A";
        $sorguBoyut2 = strlen($sorgu2);
        $sorguSonuc2 = socket_write($socket, $sorgu2, $sorguBoyut2);
        socket_recv($socket, $sonuc2, 256, 0);
        $sorgu = "\x40".$tip." ".$yazi."\x0A";
    }

    $sorguBoyut = strlen($sorgu);
    $sorguSonuc = socket_write($socket, $sorgu, $sorguBoyut);

    if ($sorguSonuc < 0)
        echo "Hata: ".socket_strerror($sorguSonuc)."\n";
    else
        $sonuc1 = socket_recv($socket, $sonuc2, 256, 0);


    if ($tip == "USER_COUNT")
    {
       $say = trim($sonuc2);
        $say = explode(' ', $say);
        //$say[0] = Kanaldaki toplam online
        //$say[1] = Kırmızı bayrak toplam online
        //$say[2] = Sarı bayrak toplam online
        //$say[3] = Mavi bayrak toplam online
        //$say[4] = Çekirdek toplam online
        return $say;
    }
    else
    {
        return "$sonuc2\n";
    }


    // P2P Baglantı kapat.
    socket_close($socket);
}


$say1 = P2PSendServer("", "USER_COUNT", 14000); //CH1


?>



Paylaşım için teşekkürler, Acaba bu konuda daha fazla bilgi nasıl edinebilirim ? Mevcur proje ve ya sistemlerden inceleyip öğrenebileceğim yol ve yöntemleri benimle paylaşabilir misiniz ?

USERCOUNT DA dönen veride $say1 icinde anlmasız karakterlerle geliyor bunun nedeni nedir peki input.cpp den mı kaynaklı oradan mı ayarlanması lazım. temzilenmesi vs .
 
Bazı fileslerde direk karakter ismi yazıyor. Kaynak kodlarından göstermek istediğiniz verileri ekleyebilirsiniz.
 
Bazı fileslerde direk karakter ismi yazıyor. Kaynak kodlarından göstermek istediğiniz verileri ekleyebilirsiniz.
Çok mantıklı bir şey aslında tekrar terkar sql sorguları yapmaktansa dırekt olarak verılerı almak söyle birşey denedim, konudaki örnekten yola cıkaraktan ekran fotografları şu şekilde;

user_count'un benzeri bir if tanımladım. sistemden cagırttım su sekılde.

input.cpp
indir-1.png


p2p.php
indir-2.png


bu şekilde okuttuğumda da bana kullanıcıları listeliyor.. :S online karakterlerin bilgilerini veriyor
 
if ($tip == "ALPER")
diye yazdığınız if blogu var. Yeni eklediğiniz değer bir dizi vermiyor. Sadece string veriyor. İf blogu şu şekilde olsun;

return trim(sonuc2);

Eğer hala veri gelmiyorsa filesiniz gelen p2p bağlantısını reddediyor olabilir. Syserr dosyalarında da yazar.
Burada ki konuya bakabilirsiniz;
Metin2 PvP Sunucu Güvenliği İçin Config Dosyasına Eklememiz Gerekenler
 
if ($tip == "ALPER")
diye yazdığınız if blogu var. Yeni eklediğiniz değer bir dizi vermiyor. Sadece string veriyor. İf blogu şu şekilde olsun;

return trim(sonuc2);

Eğer hala veri gelmiyorsa filesiniz gelen p2p bağlantısını reddediyor olabilir. Syserr dosyalarında da yazar.
Burada ki konuya bakabilirsiniz;
Metin2 PvP Sunucu Güvenliği İçin Config Dosyasına Eklememiz Gerekenler
İnanın dun aksam 22:00 gibi başladım araştırmaya uygulamaya. Şu saate kadar araştırıyorum, Asıl niyetim oyundaki shop verilerini web sitesinde görüntüleyebilmek. Bunu php sql ile yaptım fakat cok fazla ıtem ve user olan bır sunucudu tamamen cpu ve ram ısrafı dediler haklılarda bu yöntemi önerdiler, İsminiz nedir acaba bahsettiklerinizi uygulayıp dönüş yapacağım hocam.

Ve düşünüyorum da files'in src' kodlarına gore p2p de duzenlemeler yapılmıs olabılır. ALPER string değerini vermiyor.. Enterasan. Sadece Kullanıcı Online oyuncu verısını donduruyor.

Adsizc61359e330c43aa7.png

input.cpp iceriği bu şekilde,

C++:
Genişlet Daralt Kopyala
#include "stdafx.h"
#include <sstream>

#include "desc.h"
#include "desc_manager.h"
#include "char.h"
#include "buffer_manager.h"
#include "config.h"
#include "profiler.h"
#include "p2p.h"
#include "log.h"
#include "db.h"
#include "questmanager.h"
#include "login_sim.h"
#include "fishing.h"
#include "TrafficProfiler.h"
#include "priv_manager.h"
#include "castle.h"
#include "dev_log.h"
#include "../../common/service.h"

extern time_t get_global_time();

bool IsEmptyAdminPage()
{
    return g_stAdminPageIP.empty();
}

bool IsAdminPage(const char * ip)
{
    for (size_t n = 0; n < g_stAdminPageIP.size(); ++n)
    {
        if (g_stAdminPageIP[n] == ip)
            return 1;
    }  
    return 0;
}

void ClearAdminPages()
{
    for (size_t n = 0; n < g_stAdminPageIP.size(); ++n)
        g_stAdminPageIP[n].clear();

    g_stAdminPageIP.clear();
}

CInputProcessor::CInputProcessor() : m_pPacketInfo(NULL), m_iBufferLeft(0)
{
    if (!m_pPacketInfo)
        BindPacketInfo(&m_packetInfoCG);
}

void CInputProcessor::BindPacketInfo(CPacketInfo * pPacketInfo)
{
    m_pPacketInfo = pPacketInfo;
}

bool CInputProcessor::Process(LPDESC lpDesc, const void * c_pvOrig, int iBytes, int & r_iBytesProceed)
{
    const char * c_pData = (const char *) c_pvOrig;

    BYTE    bLastHeader = 0;
    int        iLastPacketLen = 0;
    int        iPacketLen;

    if (!m_pPacketInfo)
    {
        sys_err("No packet info has been binded to");
        return true;
    }

    for (m_iBufferLeft = iBytes; m_iBufferLeft > 0;)
    {
        BYTE bHeader = (BYTE) *(c_pData);
        const char * c_pszName;

        if (bHeader == 0) // 암호화 처리가 있으므로 0번 헤더는 스킵한다.
            iPacketLen = 1;
        else if (!m_pPacketInfo->Get(bHeader, &iPacketLen, &c_pszName))
        {
            sys_err("UNKNOWN HEADER: %d, LAST HEADER: %d(%d), REMAIN BYTES: %d, fd: %d",
                    bHeader, bLastHeader, iLastPacketLen, m_iBufferLeft, lpDesc->GetSocket());
            //printdata((BYTE *) c_pvOrig, m_iBufferLeft);
            lpDesc->SetPhase(PHASE_CLOSE);
            return true;
        }

        if (m_iBufferLeft < iPacketLen)
            return true;

        if (bHeader)
        {
            if (test_server && bHeader != HEADER_CG_MOVE)
                sys_log(0, "Packet Analyze [Header %d][bufferLeft %d] ", bHeader, m_iBufferLeft);

            m_pPacketInfo->Start();

            int iExtraPacketSize = Analyze(lpDesc, bHeader, c_pData);

            if (iExtraPacketSize < 0)
                return true;

            iPacketLen += iExtraPacketSize;
            lpDesc->Log("%s %d", c_pszName, iPacketLen);
            m_pPacketInfo->End();
        }

        // TRAFFIC_PROFILER
        if (g_bTrafficProfileOn)
            TrafficProfiler::instance().Report(TrafficProfiler::IODIR_INPUT, bHeader, iPacketLen);
        // END_OF_TRAFFIC_PROFILER

        if (bHeader == HEADER_CG_PONG)
            sys_log(0, "PONG! %u %u", m_pPacketInfo->IsSequence(bHeader), *(BYTE *) (c_pData + iPacketLen - sizeof(BYTE)));

        if (m_pPacketInfo->IsSequence(bHeader))
        {
            BYTE bSeq = lpDesc->GetSequence();
            BYTE bSeqReceived = *(BYTE *) (c_pData + iPacketLen - sizeof(BYTE));

            if (bSeq != bSeqReceived)
            {
                //sys_err("SEQUENCE %x mismatch 0x%x != 0x%x header %u", get_pointer(lpDesc), bSeq, bSeqReceived, bHeader);

                LPCHARACTER    ch = lpDesc->GetCharacter();

                char buf[1024];
                int    offset, len;

                offset = snprintf(buf, sizeof(buf), "SEQUENCE_LOG [%s]-------------\n", ch ? ch->GetName() : "UNKNOWN");

                if (offset < 0 || offset >= (int) sizeof(buf))
                    offset = sizeof(buf) - 1;

                for (size_t i = 0; i < lpDesc->m_seq_vector.size(); ++i)
                {
                    len = snprintf(buf + offset, sizeof(buf) - offset, "\t[%03d : 0x%x]\n",
                            lpDesc->m_seq_vector[i].hdr,
                            lpDesc->m_seq_vector[i].seq);

                    if (len < 0 || len >= (int) sizeof(buf) - offset)
                        offset += (sizeof(buf) - offset) - 1;
                    else
                        offset += len;
                }

                snprintf(buf + offset, sizeof(buf) - offset, "\t[%03d : 0x%x]\n", bHeader, bSeq);
                //sys_err("%s", buf);

                lpDesc->SetPhase(PHASE_CLOSE);
                return true;
            }
            else
            {
                lpDesc->push_seq(bHeader, bSeq);
                lpDesc->SetNextSequence();
                //sys_err("SEQUENCE %x match %u next %u header %u", lpDesc, bSeq, lpDesc->GetSequence(), bHeader);
            }
        }

        c_pData    += iPacketLen;
        m_iBufferLeft -= iPacketLen;
        r_iBytesProceed += iPacketLen;

        iLastPacketLen = iPacketLen;
        bLastHeader    = bHeader;

        if (GetType() != lpDesc->GetInputProcessor()->GetType())
            return false;
    }

    return true;
}

void CInputProcessor::Pong(LPDESC d)
{
    d->SetPong(true);


}

void CInputProcessor::Handshake(LPDESC d, const char * c_pData)
{
    TPacketCGHandshake * p = (TPacketCGHandshake *) c_pData;

    if (d->GetHandshake() != p->dwHandshake)
    {
        sys_err("Invalid Handshake on %d", d->GetSocket());
        d->SetPhase(PHASE_CLOSE);
    }
    else
    {
        if (d->IsPhase(PHASE_HANDSHAKE))
        {
            if (d->HandshakeProcess(p->dwTime, p->lDelta, false))
            {
#ifdef _IMPROVED_PACKET_ENCRYPTION_
                d->SendKeyAgreement();
#else
                if (g_bAuthServer)
                    d->SetPhase(PHASE_AUTH);
                else
                    d->SetPhase(PHASE_LOGIN);
#endif // #ifdef _IMPROVED_PACKET_ENCRYPTION_
            }
        }
        else
            d->HandshakeProcess(p->dwTime, p->lDelta, true);
    }
}

void CInputProcessor::Version(LPCHARACTER ch, const char* c_pData)
{
    if (!ch)
        return;

    TPacketCGClientVersion * p = (TPacketCGClientVersion *) c_pData;
    sys_log(0, "VERSION: %s %s %s", ch->GetName(), p->timestamp, p->filename);
    ch->GetDesc()->SetClientVersion(p->timestamp);
}

void LoginFailure(LPDESC d, const char * c_pszStatus)
{
    if (!d)
        return;

    TPacketGCLoginFailure failurePacket;

    failurePacket.header = HEADER_GC_LOGIN_FAILURE;
    strlcpy(failurePacket.szStatus, c_pszStatus, sizeof(failurePacket.szStatus));

    d->Packet(&failurePacket, sizeof(failurePacket));
}

CInputHandshake::CInputHandshake()
{
    CPacketInfoCG * pkPacketInfo = M2_NEW CPacketInfoCG;
    pkPacketInfo->SetSequence(HEADER_CG_PONG, false);

    m_pMainPacketInfo = m_pPacketInfo;
    BindPacketInfo(pkPacketInfo);
}

CInputHandshake::~CInputHandshake()
{
    if( NULL != m_pPacketInfo )
    {
        M2_DELETE(m_pPacketInfo);
        m_pPacketInfo = NULL;
    }
}


std::map<DWORD, CLoginSim *> g_sim;
std::map<DWORD, CLoginSim *> g_simByPID;
std::vector<TPlayerTable> g_vec_save;

// BLOCK_CHAT
ACMD(do_block_chat);
// END_OF_BLOCK_CHAT

int CInputHandshake::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)
{
    if (bHeader == 10) // 엔터는 무시
        return 0;

    if (bHeader == HEADER_CG_TEXT)
    {
        ++c_pData;
        const char * c_pSep;

        if (!(c_pSep = strchr(c_pData, '\n')))    // \n을 찾는다.
            return -1;
          
      
        if (!IsAdminPage(inet_ntoa(d->GetAddr().sin_addr)))
            return -1;  

/*#ifdef ENABLE_PORT_SECURITY
        if (IsEmptyAdminPage() || !IsAdminPage(inet_ntoa(d->GetAddr().sin_addr)))
        {
            sys_err("SOCKET_CMD: BLOCK FROM(%s)", d->GetHostName());
            return -1;
        }
#endif*/

        if (*(c_pSep - 1) == '\r')
            --c_pSep;

        std::string stResult;
        std::string stBuf;
        stBuf.assign(c_pData, 0, c_pSep - c_pData);

        sys_log(0, "SOCKET_CMD: FROM(%s) CMD(%s)", d->GetHostName(), stBuf.c_str());

        if (!stBuf.compare("IS_SERVER_UP"))
        {
            if (g_bNoMoreClient)
                stResult = "NO";
            else
                stResult = "YES";
        }
        //else if (!stBuf.compare("SHOWMETHEMONEY"))
        else if (stBuf == g_stAdminPagePassword)
        {
            if (!IsEmptyAdminPage())
            {
                if (!IsAdminPage(inet_ntoa(d->GetAddr().sin_addr)))
                {
                    char szTmp[64];
                    snprintf(szTmp, sizeof(szTmp), "WEBADMIN : Wrong Connector : %s", inet_ntoa(d->GetAddr().sin_addr));
                    stResult += szTmp;
                }
                else
                {
                    d->SetAdminMode();
                    stResult = "UNKNOWN";
                }
            }
            else
            {
                d->SetAdminMode();
                stResult = "UNKNOWN";
            }
        }
        else if (!stBuf.compare("USER_COUNT"))
        {
            char szTmp[64];

            if (!IsEmptyAdminPage())
            {
                if (!IsAdminPage(inet_ntoa(d->GetAddr().sin_addr)))
                {
                    snprintf(szTmp, sizeof(szTmp), "WEBADMIN : Wrong Connector : %s", inet_ntoa(d->GetAddr().sin_addr));
                }
                else
                {
                    int iTotal;
                    int * paiEmpireUserCount;
                    int iLocal;
                    DESC_MANAGER::instance().GetUserCount(iTotal, &paiEmpireUserCount, iLocal);
                    snprintf(szTmp, sizeof(szTmp), "%d ", iTotal);//, paiEmpireUserCount[1], paiEmpireUserCount[2], paiEmpireUserCount[3], iLocal
                }
            }
            else
            {
                int iTotal;
                int * paiEmpireUserCount;
                int iLocal;
                DESC_MANAGER::instance().GetUserCount(iTotal, &paiEmpireUserCount, iLocal);
                snprintf(szTmp, sizeof(szTmp), "%d ", iTotal, paiEmpireUserCount[1], paiEmpireUserCount[2], paiEmpireUserCount[3], iLocal); //sadece deniyorum,
            }
            stResult += szTmp;
        }else if (!stBuf.compare("ALPER"))
        {
                stResult += "ADIM ALPER.";
        }else if (!stBuf.compare("CAGLAR"))
        {if (IsEmptyAdminPage())
            {
                stResult = "ADIM CAGLAR.";
            }
        }
        else if (!stBuf.compare("CHECK_P2P_CONNECTIONS"))
        {
            std::ostringstream oss(std::ostringstream::out);
          
            oss << "P2P CONNECTION NUMBER : " << P2P_MANAGER::instance().GetDescCount() << "\n";
            std::string hostNames;
            P2P_MANAGER::Instance().GetP2PHostNames(hostNames);
            oss << hostNames;
            stResult = oss.str();
            TPacketGGCheckAwakeness packet;
            packet.bHeader = HEADER_GG_CHECK_AWAKENESS;

            P2P_MANAGER::instance().Send(&packet, sizeof(packet));
        }
        else if (!stBuf.compare("PACKET_INFO"))
        {
            m_pMainPacketInfo->Log("packet_info.txt");
            stResult = "OK";
        }
        else if (!stBuf.compare("PROFILE"))
        {
            CProfiler::instance().Log("profile.txt");
            stResult = "OK";
        }
        //gift notify delete command
        else if (!stBuf.compare(0,15,"DELETE_AWARDID "))
            {
                char szTmp[64];
                std::string msg = stBuf.substr(15,26);    // item_award의 id범위?
              
                TPacketDeleteAwardID p;
                p.dwID = (DWORD)(atoi(msg.c_str()));
                snprintf(szTmp,sizeof(szTmp),"Sent to DB cache to delete ItemAward, id: %d",p.dwID);
                //sys_log(0,"%d",p.dwID);
                // strlcpy(p.login, msg.c_str(), sizeof(p.login));
                db_clientdesc->DBPacket(HEADER_GD_DELETE_AWARDID, 0, &p, sizeof(p));
                stResult += szTmp;
            }
        else
        {
            stResult = "UNKNOWN";
          
            if (d->IsAdminMode())
            {
                // 어드민 명령들
                if (!stBuf.compare(0, 7, "NOTICE "))
                {
                    std::string msg = stBuf.substr(7, 50);
                    LogManager::instance().CharLog(0, 0, 0, 1, "NOTICE", msg.c_str(), d->GetHostName());
                    BroadcastNotice(msg.c_str());
                }
                else if (!stBuf.compare("SHUTDOWN"))
                {
                    LogManager::instance().CharLog(0, 0, 0, 2, "SHUTDOWN", "", d->GetHostName());
                    TPacketGGShutdown p;
                    p.bHeader = HEADER_GG_SHUTDOWN;
                    P2P_MANAGER::instance().Send(&p, sizeof(TPacketGGShutdown));
                    sys_err("Accept shutdown command from %s.", d->GetHostName());
                    Shutdown(10);
                }
                else if (!stBuf.compare("SHUTDOWN_ONLY"))
                {
                    LogManager::instance().CharLog(0, 0, 0, 2, "SHUTDOWN", "", d->GetHostName());
                    sys_err("Accept shutdown only command from %s.", d->GetHostName());
                    Shutdown(10);
                }
                else if (!stBuf.compare(0, 3, "DC "))
                {
                    std::string msg = stBuf.substr(3, LOGIN_MAX_LEN);

dev_log(LOG_DEB0, "DC : '%s'", msg.c_str());

                    TPacketGGDisconnect pgg;

                    pgg.bHeader = HEADER_GG_DISCONNECT;
                    strlcpy(pgg.szLogin, msg.c_str(), sizeof(pgg.szLogin));

                    P2P_MANAGER::instance().Send(&pgg, sizeof(TPacketGGDisconnect));

                    // delete login key
                    {
                        TPacketDC p;
                        strlcpy(p.login, msg.c_str(), sizeof(p.login));
                        db_clientdesc->DBPacket(HEADER_GD_DC, 0, &p, sizeof(p));
                    }
                }
                else if (!stBuf.compare(0, 10, "RELOAD_CRC"))
                {
                    LoadValidCRCList();

                    BYTE bHeader = HEADER_GG_RELOAD_CRC_LIST;
                    P2P_MANAGER::instance().Send(&bHeader, sizeof(BYTE));
                    stResult = "OK";
                }
                else if (!stBuf.compare(0, 20, "CHECK_CLIENT_VERSION"))
                {
                    CheckClientVersion();

                    BYTE bHeader = HEADER_GG_CHECK_CLIENT_VERSION;
                    P2P_MANAGER::instance().Send(&bHeader, sizeof(BYTE));
                    stResult = "OK";
                }
                else if (!stBuf.compare(0, 6, "RELOAD"))
                {
                    if (stBuf.size() == 6)
                    {
                        LoadStateUserCount();
                        db_clientdesc->DBPacket(HEADER_GD_RELOAD_PROTO, 0, NULL, 0);
                        DBManager::instance().LoadDBString();
                    }
                    else
                    {
                        char c = stBuf[7];

                        switch (LOWER(c))
                        {
                            case 'u':
                                LoadStateUserCount();
                                break;

                            case 'p':
                                db_clientdesc->DBPacket(HEADER_GD_RELOAD_PROTO, 0, NULL, 0);
                                break;

                            case 's':
                                DBManager::instance().LoadDBString();
                                break;

                            case 'q':
                                quest::CQuestManager::instance().Reload();
                                break;

                            case 'f':
                                fishing::Initialize();
                                break;

                            case 'a':
                                db_clientdesc->DBPacket(HEADER_GD_RELOAD_ADMIN, 0, NULL, 0);
                                sys_log(0, "Reloading admin infomation.");
                                break;
                        }
                    }
                }
                else if (!stBuf.compare(0, 6, "EVENT "))
                {
                    std::istringstream is(stBuf);
                    std::string strEvent, strFlagName;
                    long lValue;
                    is >> strEvent >> strFlagName >> lValue;

                    if (!is.fail())
                    {
                        sys_log(0, "EXTERNAL EVENT FLAG name %s value %d", strFlagName.c_str(), lValue);
                        quest::CQuestManager::instance().RequestSetEventFlag(strFlagName, lValue);
                        stResult = "EVENT FLAG CHANGE ";
                        stResult += strFlagName;
                    }
                    else
                    {
                        stResult = "EVENT FLAG FAIL";
                    }
                }
                // BLOCK_CHAT
                else if (!stBuf.compare(0, 11, "BLOCK_CHAT "))
                {
                    std::istringstream is(stBuf);
                    std::string strBlockChat, strCharName;
                    long lDuration;
                    is >> strBlockChat >> strCharName >> lDuration;

                    if (!is.fail())
                    {
                        sys_log(0, "EXTERNAL BLOCK_CHAT name %s duration %d", strCharName.c_str(), lDuration);

                        do_block_chat(NULL, const_cast<char*>(stBuf.c_str() + 11), 0, 0);

                        stResult = "BLOCK_CHAT ";
                        stResult += strCharName;
                    }
                    else
                    {
                        stResult = "BLOCK_CHAT FAIL";
                    }
                }
                // END_OF_BLOCK_CHAT
                else if (!stBuf.compare(0, 12, "PRIV_EMPIRE "))
                {
                    int    empire, type, value, duration;
                    std::istringstream is(stBuf);
                    std::string strPrivEmpire;
                    is >> strPrivEmpire >> empire >> type >> value >> duration;

                    // 최대치 10배
                    value = MINMAX(0, value, 1000);
                    stResult = "PRIV_EMPIRE FAIL";

                    if (!is.fail())
                    {
                        // check parameter
                        if (empire < 0 || 3 < empire);
                        else if (type < 1 || 4 < type);
                        else if (value < 0);
                        else if (duration < 0);
                        else
                        {
                            stResult = "PRIV_EMPIRE SUCCEED";

                            // 시간 단위로 변경
                            duration = duration * (60 * 60);

                            sys_log(0, "_give_empire_privileage(empire=%d, type=%d, value=%d, duration=%d) by web",
                                    empire, type, value, duration);
                            CPrivManager::instance().RequestGiveEmpirePriv(empire, type, value, duration);
                        }
                    }
                }
                else if (!stBuf.compare(0, 15, "BLOCK_EXCEPTION"))
                {
                    // BLOCK_EXCEPTION cmd(add=1, del=2) login
                    std::istringstream is(stBuf);
                    std::string    dummy_string;
                    std::string    login_string;
                    int            cmd;

                    is >> dummy_string >> cmd >> login_string;

                    sys_log(0, "block_exception %s:%d", login_string.c_str(), cmd);
                    DBManager::instance().RequestBlockException(login_string.c_str(), cmd);
                    stResult = "BLOCK_EXCEPTION_YES";
                }
            }
        }

        sys_log(1, "TEXT %s RESULT %s", stBuf.c_str(), stResult.c_str());
        stResult += "\n";
        d->Packet(stResult.c_str(), stResult.length());
        return (c_pSep - c_pData) + 1;
    }
    else if (bHeader == HEADER_CG_MARK_LOGIN)
    {
        if (!guild_mark_server)
        {
            // 끊어버려! - 마크 서버가 아닌데 마크를 요청하려고?
            sys_err("Guild Mark login requested but i'm not a mark server!");
            d->SetPhase(PHASE_CLOSE);
            return 0;
        }

        // 무조건 인증 --;
        sys_log(0, "MARK_SERVER: Login");
        d->SetPhase(PHASE_LOGIN);
        return 0;
    }
    else if (bHeader == HEADER_CG_STATE_CHECKER)
    {
        if (d->isChannelStatusRequested()) {
            return 0;
        }
        d->SetChannelStatusRequested(true);
        db_clientdesc->DBPacket(HEADER_GD_REQUEST_CHANNELSTATUS, d->GetHandle(), NULL, 0);
    }
    else if (bHeader == HEADER_CG_PONG)
        Pong(d);
    else if (bHeader == HEADER_CG_HANDSHAKE)
        Handshake(d, c_pData);
#ifdef _IMPROVED_PACKET_ENCRYPTION_
    else if (bHeader == HEADER_CG_KEY_AGREEMENT)
    {
        // Send out the key agreement completion packet first
        // to help client to enter encryption mode
        d->SendKeyAgreementCompleted();
        // Flush socket output before going encrypted
        d->ProcessOutput();

        TPacketKeyAgreement* p = (TPacketKeyAgreement*)c_pData;
        if (!d->IsCipherPrepared())
        {
            sys_err ("Cipher isn't prepared. %s maybe a wer.", inet_ntoa(d->GetAddr().sin_addr));
            d->DelayedDisconnect(5);
            return 0;
        }
        if (d->FinishHandshake(p->wAgreedLength, p->data, p->wDataLength)) {
            // Handshaking succeeded
            if (g_bAuthServer) {
                d->SetPhase(PHASE_AUTH);
            } else {
                d->SetPhase(PHASE_LOGIN);
            }
        } else {
            sys_log(0, "[CInputHandshake] Key agreement failed: al=%u dl=%u",
                p->wAgreedLength, p->wDataLength);
            d->SetPhase(PHASE_CLOSE);
        }
    }
#endif // _IMPROVED_PACKET_ENCRYPTION_
    else
        sys_err("Handshake phase does not handle packet %d (fd %d)", bHeader, d->GetSocket());

    return 0;
}
 
Son düzenleme:
İsmim profilde yazıyor. :)
Bu yöntem daha sağlıklı ama şöyle de bir yöntem yapabilirsiniz. Cache kullanarak sorgu oluşturabilirsiniz. Mesela günde bir kez gibi.
Tam olarak istediğiniz şeyi detaylandırabilir misiniz?

Kod:
Genişlet Daralt Kopyala
Dec  7 17:53:01 :: SYSTEM: new p2p connection from [192.168.1.100] to [192.168.1.112] fd: 20 BLOCKED
Dec  7 17:53:01 :: DESC_MANAGER::AcceptP2PDesc  192.168.1.100:53081
Dec  7 17:53:01 :: P2P Acceptor opened (host 192.168.1.100)
Dec  7 17:53:01 :: P2P Acceptor closed (host 192.168.1.100)

192.168.1.100 benim makinem
192.168.1.112 freebsd

Bağlanmaya çalıştığımda hata veriyor. Bunu gidermenin yolu adminpage ve public_ip kısmına makinanızın ip adresini yazmalısınız. php dosyalarında da kanalların p2p_portlarını doğru girdiğinizden emin olunuz.
 
C++:
Genişlet Daralt Kopyala
snprintf(szTmp, sizeof(szTmp), "%d ", iTotal, paiEmpireUserCount[1], paiEmpireUserCount[2], paiEmpireUserCount[3], iLocal); //sadece deniyorum,

burdaki düzensizliğe aldanmayın niyetim denemekti olması gereken söyle
C++:
Genişlet Daralt Kopyala
snprintf(szTmp, sizeof(szTmp), "%d %d %d %d %d ", iTotal, paiEmpireUserCount[1], paiEmpireUserCount[2], paiEmpireUserCount[3], iLocal);
İsmim profilde yazıyor. :)
Bu yöntem daha sağlıklı ama şöyle de bir yöntem yapabilirsiniz. Cache kullanarak sorgu oluşturabilirsiniz. Mesela günde bir kez gibi.
Tam olarak istediğiniz şeyi detaylandırabilir misiniz?

İnanın adınızı göremedim ama Samsunlusunuz,Öğrencisiniz, 22 yaşında bir erkeksiniz vs :)
Bu arada Adım Alper Sivaslıyım 58 yakın sayılırız. 25 yaşımdayım.

Cache olmaz kesinlikle sistemin anlık olması gerekıyor.

ip ve portlarda mevzu yok degerlerı cekıyor peki tcp ile veri cekerken her seferinde farklı bır oturum olusturmak ve oradan verı cekmek mı lazım ? veya farklı bir port uzerınden iletisim sağlamak gibi ?

Örnek video url'i atıyım size hocam çok emek verdim ama düşünmeden yaptım kucuk pvplerde problem olmaz fakat server büyüdükce problem cıkartacaktır 5k anlık etkilesimde yuklu mıktarda cpu kullanacaktır. sadece web sitesi



İsmim profilde yazıyor. :)
Bu yöntem daha sağlıklı ama şöyle de bir yöntem yapabilirsiniz. Cache kullanarak sorgu oluşturabilirsiniz. Mesela günde bir kez gibi.
Tam olarak istediğiniz şeyi detaylandırabilir misiniz?

Kod:
Genişlet Daralt Kopyala
Dec  7 17:53:01 :: SYSTEM: new p2p connection from [192.168.1.100] to [192.168.1.112] fd: 20 BLOCKED
Dec  7 17:53:01 :: DESC_MANAGER::AcceptP2PDesc  192.168.1.100:53081
Dec  7 17:53:01 :: P2P Acceptor opened (host 192.168.1.100)
Dec  7 17:53:01 :: P2P Acceptor closed (host 192.168.1.100)

192.168.1.100 benim makinem
192.168.1.112 freebsd

Bağlanmaya çalıştığımda hata veriyor. Bunu gidermenin yolu adminpage ve public_ip kısmına makinanızın ip adresini yazmalısınız. php dosyalarında da kanalların p2p_portlarını doğru girdiğinizden emin olunuz.
Son olarakta :) port için ch1'in p2p portunu kullandım hocam online verileri yansıtıyor anlık olaraktan. php kısmında saydıracagım sadece dizinde kac tane değer var gibi ama diger kısmı daha basıt olan tarafı çözemedim. Sayın amirim,
 
En son bir moderatör tarafından düzenlenmiş:
tcp bağlantı türü her kullanıcı için ayrı bir bağlantı oluşturur. Yerel ve uzak makina bağlantıyı kapatmadığı sürece bağlantı sürekli sağlanır. Cache yapamıyorsanız bu şekilde yapıyı kurmanız gerekiyor.

Online verileri aldıysanız bağlantı sağlanıyor demektir.

Şunu bi dener misiniz bakalım veri döndüremiyor mu?
PHP:
Genişlet Daralt Kopyala
$say1 = P2PSendServer("", "IS_SERVER_UP", 30004); //CH1

port kısmını kendi serverinize göre düzenleyiniz.

Bu işlemi yaptıktan sonra bağlandığınız kanalın syslog dosyasına bakın. Orada gelen ve gönderilen veriler yazıyor.
 
tcp bağlantı türü her kullanıcı için ayrı bir bağlantı oluşturur. Yerel ve uzak makina bağlantıyı kapatmadığı sürece bağlantı sürekli sağlanır. Cache yapamıyorsanız bu şekilde yapıyı kurmanız gerekiyor.

Online verileri aldıysanız bağlantı sağlanıyor demektir.

Şunu bi dener misiniz bakalım veri döndüremiyor mu?
PHP:
Genişlet Daralt Kopyala
$say1 = P2PSendServer("", "IS_SERVER_UP", 30004); //CH1

port kısmını kendi serverinize göre düzenleyiniz.

Bu işlemi yaptıktan sonra bağlandığınız kanalın syslog dosyasına bakın. Orada gelen ve gönderilen veriler yazıyor.
syserr

SYSERR: Dec 7 16:24:45 :: Process: UNKNOWN HEADER: 73, LAST HEADER: 0(0), REMAIN BYTES: 12, fd: 17

syslog

Dec 7 16:25:26 :: SYSTEM: new p2p connection from [192.168.1.103] fd: 17
Dec 7 16:25:26 :: DESC_MANAGER::AcceptP2PDesc 192.168.1.103:55401
Dec 7 16:25:26 :: P2P Acceptor opened (host 192.168.1.103)
SYSERR: Dec 7 16:25:26 :: Process: UNKNOWN HEADER: 73, LAST HEADER: 0(0), REMAIN BYTES: 12, fd: 17
Dec 7 16:25:26 :: P2P Acceptor closed (host 192.168.1.103)
Dec 7 16:25:26 :: SYSTEM: closing p2p socket. DESC #17

Bunu php kısmında ekran cıktısı yok
 
Ekrana herhangi bir şey yazdırmıyor mu?
 
game/src/packet.h dosyasında 73 değerine ait header var mı? Bi kontrol eder misiniz?
 
Geri
Üst