Fethi Polat 1
Fethi Polat
xranzei 1
xranzei
Bvural41 1
Bvural41
kralhakan2009 1
kralhakan2009
noisiv 1
noisiv
Manwe Work 1
Manwe Work
Vahsi Uzman 1
Vahsi Uzman
Cannn6161 1
Cannn6161
Hikaye Ekle
Reklam vermek için turkmmo@gmail.com

P2P VE CLIENT UNKNOWN HEADER SYSERRI ARKAPLANI

  • Konuyu başlatan Konuyu başlatan victory80
  • Başlangıç tarihi Başlangıç tarihi
  • Cevaplar Cevaplar 11
  • Görüntüleme Görüntüleme 2K

ROHAN2 WORLD 1-120 TR TİPİ OFFICIAL YOHARA, BALATHOR VE AMON! 80. GÜNÜNDE! +10.000 ONLİNE! HİLE VE BOT %100 ENGELLİ HEMEN TIKLA!

Ben bu konu hakkında biraz kafa yormuştum TCP protokolü ve Paketli iletişimler hakkında vs. Şimdi paket tabanlı iletişimlerde şunlara dikkat etmek gerekiyor.

1: Paket boyutu uyuşmazlığı
2: Veri bozulması(İletim sırasında)
3: Yanlış paket sıralaması(TCP protokolüne uygun sıralanmaması)
4: Eksik veya Hatalı başlık(header) bilgisi
5: Beklenmeyen veri tipleri
6: Yetersiz Hata yöntemi

Mesela yetersiz hata yönetimi hakkında örneğin bir paketin beklenenden büyük olması durumunda ve bu hata yakalanıp düzgün bir şekilde işlenmezse oyundan atma yaşanır.
Ekleme için teşekkür ederim,

Hata yönetimi konusunda bir düzenlemeniz oldu mu?
Buffered olmayan paket yapısı içerisinde herhangi bir size bilgisi bulunmuyor. Yani clientin bu paketleri teslim alırken kontrol ettiği sadece tcp uzerınden akan verinin boyutudur ki bu da çok sağlıklı görünmüyor. Belki BYTE bHeader altına int iSize gibi bir veri yollayabiliriz diye düşünmüştüm ben de. Biliyorsunuz, hali hazırda zaten buffered paketler bu yapıda. Fakat diğerleri bu yapıda değil.
 
İnternet bağlantısı stabil oyuncular için bu sorunun tespiti için nasıl bir yol izleyebileceğimiz konusunda kararsızım açıkçası.

temel olarak bahsettiğim şekilde paket gönderim sisteminin düzenlenmesi gerekiyor. mevcut haliyle en temel olarak CInputProcessor::Process fonksiyonunda paket işleme sisteminin nasıl çalıştığını görebilirsiniz. mevcut haliyle sadece header idini arayıp onun tanımlı olduğu paket boyutu kadar işleme sokuyor.

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

if (bHeader == 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;

bu kısmı daha güvenli bir şekilde düzenlemeden bu sorunun önüne geçemezsiniz, örnek olarak kapsamlı bir şekilde;
for (m_iBufferLeft = iBytes; m_iBufferLeft > 0;)
{
if (m_iBufferLeft < sizeof(PacketHeader))
{
return true; // Not enough data to read the header
}

const PacketHeader* packetHeader = reinterpret_cast<const PacketHeader*>(c_pData);
uint16_t packetId = packetHeader->id;
uint32_t packetSize = packetHeader->size;

if (m_iBufferLeft < packetSize)
{
return true; // Not enough data to read the entire packet
}

std::string strName;
bool bIsStatic = false;

if (!m_pPacketInfo->Get(packetId, packetSize, strName, bIsStatic))
{
LogUnknownHeader(lpDesc, packetId);
lpDesc->SetCloseReason("WRONG_PACKET_HEADER");
lpDesc->SetPhase(PHASE_CLOSE);
return true;
}

if (bIsStatic && !ValidatePacketSize(packetId, packetSize, lpDesc))
{
lpDesc->SetCloseReason("WRONG_PACKET_LENGTH");
lpDesc->SetPhase(PHASE_CLOSE);
return true;
}

m_pPacketInfo->Start();
int32_t iExtraPacketSize = Analyze(lpDesc, packetId, c_pData + sizeof(PacketHeader));

ve header kısmı için paket verisinden bağımsız olarak mevcut halindeki "TDynamicSizePacketHeader" gibi bir header üzerinden veriyi tanımlamanız gerekir örnek olarak;
#pragma pack(push, 1)
struct PacketHeader
{
uint16_t id; // Packet ID
uint32_t size; // Size of the packet
uint32_t hash; // Hash for integrity check
uint32_t order_sec_id; // Order section identifier (aka. sequence)
uint8_t flags; // Flags for encryption/compression

PacketHeader(uint16_t id, uint32_t size, uint32_t hash, uint32_t order_sec_id, uint8_t flags) :
id(id), size(size), hash(hash), order_sec_id(order_sec_id), flags(flags)
{
}
};
#pragma pack(pop)

bütün network transferini bu şekilde yaparsanız, asio gibi nispeten daha güvenli bir yapı üzerinden iletişim sağlarsanız ve bufferları buradan yönetirseniz, şifreleme içinde bufferların işleme mantığını tekrar gözden geçirirseniz hiçbir problem yaşamazsınız.
 
Aklıma oyuncunun interneti de geldi yazmayı unuttum :) Eğer oyuncunun anlık interneti giderse veya yavaşlarsa timeout ve Latency olur. Yani paket iletim sırasında paket kaybolur ve oyuncu disconnect olur. Aslında TCP paketi yeniden işleyip gönderme yapabiliyor Metin2 de bu var mı bilmiyorum hiç oralara bakmadım. :) Ayrıca Gameden Cliente paket geldiğinde Client paketi ve boyutları bilip bu boyutlarda bir değişiklik sezmesi durumunda tekrar gameden bunu işletmesini isteyebilir.
 
Merhaba, öncelikle bu baş belası sorunla uğraşırken sabır diliyorum, bu oyunun kaynağında açık ara en nefret ettiğim yer Ymir'in el yapımı network paket sistemi. Oyunun geliştirildiği yılları baz alınca henüz ortada tcp paket alışverişi, socket yapısı ve buffer ayarlamalarıyla alakalı yardımcı kütüphaneler yoktu, veya yoktu demeyelim de çok az sayıda vardı, bu yüzden bunu kendileri yapmış, takdir etmekle birlikte çok kötü bir sistem olduğunu, paket alışverişinde bir sorun yaşanma ihtimalinin de pamuk ipliğine bağlı olduğunu unutmamak gerekiyor. Her şey sorunsuz, client ve server arasında alışverişi bozabilecek bir kod hatası yok diyelim, sadece oyun serverinin internet bağlantısındaki bir sıkıntı, oyuncuların bilgisayarlarındaki herhangi bir anlık problem bile bu hatayı tetikleyebilir çünkü paketlerin sağlıklı şekilde iletimi ve dahası bu iletimi denetlemek için yeterli kontrol mekanizması mevcut değil, bu durumu kökten çözmek için yapılabilecek en mantıklı hareket Aeldra'nın da yaptığı gibi tüm paket sistemini Google'ın protobuf kütüphanesini kullanarak yenilemek, iletim kalitesinde, sorunların ele alınmasında ve hata analizinde inanılmaz kolaylık sağlayacağına eminim fakat çok büyük bir işlem ve çok fazla değişiklik gerekiyor, Aeldra'nın warez olan dosyalarında yapıyı inceleyebilirsiniz.

Anlattığınız problem için pansuman olacak çözüm zaten yıllar önce Ymir tarafından yapılmış, çünkü kolaya kaçarak yapılabilecek en iyi yöntem buydu, neydi bu yöntem; paketleri hem iletim olarak hem boyut olarak kısıtlamak, böylece ele almak gereken paket sayısı daha az olacak ve karışıklık veya başarısız iletim yaşama şansını azaltacaklardı ayrıca oyuncu kaynaklı veya sunucu kaynaklı internet problemleri ve hız sorunları baş gösterdiğinde sorun yaşama şansları minimuma inecekti. Bahsettiğim şey client kaynak kodlarındaki şu bölüm, burada kendi kullandığım versiyonunu ve düştüğüm yorumu da paylaşmış olayım;

C++:
    // INFO: Explanation is needed for MAX_RECV_COUNT and SAFE_RECV_BUFSIZE..
    //       Ymir set it to 4 and set bufsize 8KB but it was 2004 when they were doing it,
    //       We need keep this low still but 4 is too low for nowadays. (Because internet speeds are much higher now)
    //       But it doesn't make sense to make it something like 32 or 64, we have some players still play this game in old computers and bad internet speeds.
    //       And also thats still too much for live server in some cases (Ex: 5.000 online players and 1Gbit internet speed, it's still too much)
    //       This feature should definitely NOT be removed!
    //       If the restriction is removed on a server with very high player counts, players may be kicked out of the game due to packet problems %100.
    //       In my opinion, 8 Recv and 8KB Buf would be the ideal setting for this one. - [MT2Dev Note] - 21/02/2024
    const DWORD MAX_RECV_COUNT        = 8;
    const DWORD SAFE_RECV_BUFSIZE    = 8192;
    DWORD dwRecvCount                = 0;

Tahminime göre siz bu değerleri (en azından recv countu) arttırdınız, eğer arttırmadıysanız söylediklerimi önemsemeyebilirsiniz ama eğer arttırdıysanız tavsiyem ayarlarınızı maksimum bu şekilde ayarlamanız ve tek seferde 8KB fazlası paket gönderen fonksiyonlarınızı kısıtlamanız (Örnek; 15KB'lık offline shop paketiniz), bu oyunun paket sistemi değişmediği sürece Ymir'in zamanında pansuman olarak yaptığı şeyleri değiştirmemek gerek, bunu belirli bir sebeple yaptıkları aşikar, sevgiler.
 
Paylaşım için teşekkürler.
 

Şu an konuyu görüntüleyenler (Toplam : 0, Üye: 0, Misafir: 0)

Geri
Üst