Metin2 serverinfo.py: Client'ı Sunucuya Bağlama
Hazırlayan: Metin2VIP Editörleri Yayın: 7 dk okuma
İçindekiler
serverinfo.py, istemcinin root paketinde duran ve giriş ekranının sunucu adını, adresini, auth portunu ve kanal portlarını okuduğu Python dosyasıdır. Adres IP de olabilir alan adı da. Auth portu auth sunucusunun, kanal portları ise o kanaldaki bir oyun çekirdeğinin CONFIG dosyasındaki PORT değeriyle birebir aynı olmalıdır.
Dosya root paketinin içinde olduğu için değiştirdikten sonra root paketini yeniden oluşturmak gerekir; paket biçimi Metin2 pack dosyaları yazısında. Aşağıdaki anlatım bu dosyayı, giriş ekranının kodunu ve istemci ile sunucunun ağ kaynak kodunu esas alır.
serverinfo.py'de neler yazar?
Kaynakla gelen istemcideki dosyanın yapısı aşağıdaki gibidir. Adres yerine örnek bir alan adı konuldu, geri kalanı aynıdır:
import app
import localeInfo
app.ServerName = None
SRV1 = {
"name":"SunucuAdi",
"host":"oyun.example.com",
"auth1":30001,
"ch1":30003,
"ch2":30009,
"ch3":30015,
"ch4":30021,
}
STATE_NONE = "|cFFdadada" + localeInfo.CHANNEL_STATUS_OFFLINE
STATE_DICT = {
0 : "|cFFffffff" + localeInfo.CHANNEL_STATUS_OFFLINE,
1 : "|cFF00ff00" + localeInfo.CHANNEL_STATUS_RECOMMENDED,
2 : "|cFFffc000" + localeInfo.CHANNEL_STATUS_BUSY,
3 : "|cFFff0000" + localeInfo.CHANNEL_STATUS_FULL,
}
SERVER1_CHANNEL_DICT = {
1:{"key":11,"name":"CH1","ip":SRV1["host"],"tcp_port":SRV1["ch1"],"udp_port":SRV1["ch1"],"state":STATE_NONE,},
2:{"key":12,"name":"CH2","ip":SRV1["host"],"tcp_port":SRV1["ch2"],"udp_port":SRV1["ch2"],"state":STATE_NONE,},
3:{"key":13,"name":"CH3","ip":SRV1["host"],"tcp_port":SRV1["ch3"],"udp_port":SRV1["ch3"],"state":STATE_NONE,},
4:{"key":14,"name":"CH4","ip":SRV1["host"],"tcp_port":SRV1["ch4"],"udp_port":SRV1["ch4"],"state":STATE_NONE,},
}
REGION_AUTH_SERVER_DICT = {
0 : {
1 : { "ip":SRV1["host"], "port":SRV1["auth1"], },
}
}
REGION_DICT = {
0 : {
1 : { "name" :SRV1["name"], "channel" : SERVER1_CHANNEL_DICT, },
},
}
MARKADDR_DICT = {
10 : { "ip" : SRV1["host"], "tcp_port" : SRV1["ch1"], "mark" : "10.tga", "symbol_path" : "10", },
}
Kanal portları arasındaki 6'lık aralık, her kanalda üç çekirdek çalıştıran ve her çekirdeğe iki port (PORT ve P2P_PORT) ayıran bir düzene uyar. Kaynakla gelen sunucu dosyalarında 1. kanalın çekirdekleri 30003, 30005 ve 30007 portlarını, P2P için bir fazlasını kullanıyor. Kendi sunucunda bu sayılar farklıysa serverinfo.py de ona göre yazılır.
Alanlar ne anlama geliyor?
| Alan | Anlamı | Sunucudaki karşılığı |
|---|---|---|
name |
Sunucu listesinde görünen ad | Yok, yalnız görüntü |
host |
Sunucunun adresi, IP ya da alan adı | Oyuncuların ulaştığı adres |
auth1 |
Auth sunucusunun portu | auth klasöründeki CONFIG'in PORT değeri |
ch1 ... ch4 |
Her kanalın giriş portu | O kanaldaki bir çekirdeğin CONFIG PORT değeri |
key |
bölge × 1000 + sunucu × 10 + kanal (11 = 0. bölge, 1. sunucu, 1. kanal) | Yok |
tcp_port, udp_port |
Kanalın portu; udp_port kanal durumu eşlemesinde kullanılır |
Çekirdeğin PORT değeri |
state |
Kanal durumu yazısı; istemci kendisi doldurur | Yok |
REGION_AUTH_SERVER_DICT |
Auth adresi ve portu | auth CONFIG'i |
REGION_DICT |
Sunucu listesi ve her sunucunun kanal sözlüğü | Yok |
MARKADDR_DICT |
Lonca işareti sunucusu | Bu istemcide okunmuyor |
Bu istemcinin giriş ekranı kanal düğmelerinde doğrudan SRV1 sözlüğünü kullanır: adresi host, auth portunu auth1, kanal portunu chN alanından alır. Kanal sözlüğündeki ip ve udp_port alanları yalnız kanal durumunu sorarken okunur. MARKADDR_DICT tanımlıdır ama hiçbir yerde kullanılmaz; lonca işaretleri host adresi ve CH1 portu üzerinden indirilir. Düğme sayısı giriş ekranının kodunda dört olarak sabittir, bu yüzden beşinci bir kanal için serverinfo.py'ye satır eklemek yetmez; giriş ekranının betiği ve arayüz düzeni de değişmelidir.
IP mi alan adı mı?
İstemci, adres rakamla başlamıyorsa onu alan adı sayar ve çözümler. Bu yüzden host alanına alan adı yazmak, sunucu taşındığında istemciyi yeniden dağıtmadan adresi değiştirmeyi sağlar. Auth, kanal, kanal durumu ve lonca işareti bağlantıları bu adresle kurulur. Karakter seçildikten sonraki bağlantı ise sunucunun bildirdiği sayısal adrese yapılır; o adresin doğru olması sunucu tarafının işidir.
Girişte hangi bağlantılar kurulur?
- Oyuncu bir kanal düğmesine bastığında istemci kanalın adresini ve portunu, auth adresini ve portunu hafızaya alır.
- Kullanıcı adı ve parola girilince istemci auth portuna bağlanır. Bu istemcide
constInfo.KEEP_ACCOUNT_CONNETION_ENABLE = 1olduğu için giriş her zaman auth üzerinden yapılır. - Auth ile el sıkışılır, saat eşitlenir, iki taraf şifreleme anahtarında anlaşır; ardından kullanıcı adı ve parola şifreli olarak gönderilir.
- Giriş başarılıysa auth bir giriş anahtarı (login key) döner. Şifreli paket kullanan sunucularda paket anahtarları da bu anda gelir. Auth bağlantısı kapatılır.
- İstemci kanal portuna bağlanır ve giriş anahtarıyla oturum açar. Karakter listesi gelir; listede her karakter için o karakterin haritasını çalıştıran çekirdeğin adresi ve portu da yazar.
- Oyuncu karakter seçince istemci bu adrese yeniden bağlanır ve oyuna girer.
Karakter seçince bağlantı kopuyorsa
Oyun çekirdeği oyunculara bildireceği adresi açılışta makinenin ağ kartlarından bulur. 192.168 ve 10 ile başlayan adresleri iç ağ adresi sayar. Makinede genel bir adres bulamazsa bu kaynakta açık olan bir ayar yüzünden iç ağ adresini kullanır. Bu durumda dışarıdaki oyuncular auth'a ve kanala bağlanabilir ama karakter seçince sunucunun bildirdiği iç adrese ulaşamaz ve bağlantı kopar.
Çözüm CONFIG dosyasındadır. BIND_IP çekirdeğin adresini elle verir; çekirdek soketlerini de bu adrese açtığı için adres makinenin kendisine ait olmalıdır. Makine NAT arkasındaysa PROXY_IP kullanılır: soketlere dokunmaz, yalnız oyunculara karakter listesinde ve ışınlanmalarda bildirilen adresi değiştirir. İki ayarın ayrıntısı CONFIG ayarları yazısında.
Kanal durumu nasıl gelir?
Giriş ekranı kanal durumlarını tek bir sorguyla ister. İstemci listedeki ilk kanalın (pratikte CH1) adresine ve portuna TCP ile bağlanır, tek baytlık bir istek yollar. Çekirdek isteği veritabanı çekirdeğine (db) iletir; db, kendisine bağlı bütün çekirdeklerin port ve durum listesini döner. İstemci listedeki her kaydı, udp_port değeri o porta eşit olan kanala yazar.
Her çekirdek durumunu açılışta ve sonra 5 dakikada bir db'ye bildirir. Durum şöyle hesaplanır:
| Değer | Giriş ekranında | Koşul |
|---|---|---|
| 0 | Bilinmeyen (beyaz) | Çekirdek yeni oyuncu kabul etmiyor (CONFIG'de shutdowned ya da kapanma geri sayımı) |
| 1 | Tavsiye edilen (yeşil) | Aşağıdakilerin hiçbiri değil |
| 2 | Kalabalık (turuncu) | Oyuncu sayısı kalabalık eşiğini aşıyor |
| 3 | Dolu (kırmızı) | Oyuncu sayısı dolu eşiğini aşıyor |
Eşikler kodda dolu için 500, kalabalık için 10'dur. Çekirdeğin klasöründeki state_user_count dosyası iki sayıyla ("dolu kalabalık") bu değerleri değiştirir; GM /reload u komutuyla dosya yeniden okunur. Sayılan oyuncu, çekirdeğin kendi oyuncuları ile P2P üzerinden gördüğü oyuncuların toplamıdır.
Bu işleyişin üç pratik sonucu var:
udp_portadına rağmen bağlantı TCP'dir. Değer çekirdeğinPORTdeğeri olmalıdır, ayrı bir UDP portu açılmaz.- İlk kanalın çekirdeği kapalıysa hiçbir kanalın durumu gelmez. Bütün kanallar "Bilinmeyen" kalır, diğer kanallar açık olsa bile.
- Durum gecikmeli değişir. Kalabalıklaşan bir kanal en geç 5 dakika sonra "Kalabalık" görünür.
Client ve sunucu sürümü eşleşmeli
İstemci ile sunucunun birbirini anlaması üç katmanda denetlenir.
Sürüm metni. İstemci yükleme ekranında sunucuya sabit bir metin yollar (1215955205). Sunucu bu metni CONFIG'deki CHECK_VERSION_VALUE değeriyle karşılaştırır; varsayılan değer aynı metindir ve denetim CHECK_VERSION_SERVER ile açılıp kapanır, varsayılanı açıktır. Uymazsa oyuncu oyuna girer girmez "İstemci versionunuz hatalı. Lütfen normal sürümü yükleyin." mesajıyla atılır. İstemci kaynağındaki Version.h dosyasındaki sürüm numarası bu denetime katılmaz, yalnız exe'nin dosya sürümüdür. Sabit bir metin karşılaştırıldığı için bu denetim bir güvenlik önlemi değil, uyumluluk kontrolüdür.
Paket yapısı. İki tarafın paket tanımları aynı olmalıdır. Örnek: ENABLE_PLAYER_PER_ACCOUNT5 sunucuda hesap başına karakter sayısını 5 yapar, istemcide de karakter listesi paketini 5 kişilik okur. Biri açık biri kapalıysa paket boyları tutmaz ve okunan veri kayar. Böyle bir uyumsuzlukta istemci çoğu zaman syserr.txt'ye "Unknown packet header" yazıp kapanır; sunucu tarafında tanımadığı bir başlık gelirse syserr'e "UNKNOWN HEADER" yazıp bağlantıyı keser. Paket şifrelemesini belirleyen _IMPROVED_PACKET_ENCRYPTION_ bayrağı da iki tarafta birlikte tanımlı olmalıdır. Bayrakların nerede durduğu Metin2 source derleme yazısında.
Veri. İstemcinin item_proto ve mob_proto kopyaları sunucudaki verilerle aynı kaynaktan üretilmelidir; aksi hâlde eşya adları ve ipuçları sunucunun uyguladığından farklı görünür. Şifreli paket kullanılıyorsa sunucudaki anahtar dosyaları istemcideki paketlerle aynı paketleme işinden çıkmalıdır.
Bağlanamıyorum: belirtiye göre neden
| Ekrandaki mesaj ya da belirti | Olası neden |
|---|---|
| "Sunucuya bağlanırken hata" | Auth'a ulaşılamıyor: host yanlış, auth1 auth CONFIG'indeki PORT ile aynı değil, auth çalışmıyor ya da port güvenlik duvarında kapalı. |
| "Hesap ismi veya şifre yanlış." | Sunucu NOID ya da WRONGPWD döndü. |
| "Hesabın zaten bağlı." | Hesap başka bir oturumda açık (ALREADY). |
| "Sunucu henüz açılmadı." | Çekirdek yeni oyuncu kabul etmiyor (SHUTDOWN): CONFIG'de shutdowned var ya da kapanma geri sayımı başladı. |
| "Çok fazla kullanıcı bağlı olduğu için bağlanamazsınız." | Oyuncu sayısı CONFIG'deki USER_LIMIT değerine ulaştı (varsayılan 32768). |
| Giriş başarılı, karakter seçince kopma | Sunucunun bildirdiği adres dışarıdan erişilemiyor ya da karakterin haritasını çalıştıran çekirdek kapalı. |
| Bütün kanallar "Bilinmeyen" | İlk kanalın çekirdeği kapalı ya da udp_port değerleri çekirdek portlarıyla tutmuyor. |
| Giriş ya da yükleme sırasında istemci kapanıyor, syserr'de "Unknown packet header" | İstemci ile sunucunun paket tanımları farklı; iki taraf farklı özellik bayraklarıyla derlenmiş. |
| Oyuna girince "İstemci versionunuz hatalı" | Sürüm metni ile CHECK_VERSION_VALUE farklı. |
Oyuncunun kendi bilgisayarından kaynaklanan sorunlar için istemci hataları yazısına bakılabilir.
Hangi portlar dışarıya açık olmalı?
Oyuncunun ulaşması gereken portlar yalnız auth'un PORT değeri ve kanal çekirdeklerinin PORT değerleridir. Kanal durumu ve lonca işaretleri de kanal portu üzerinden geçer.
Sık sorulan sorular
- serverinfo.py'ye IP yerine alan adı yazılabilir mi?
- Evet. İstemci rakamla başlamayan adresi alan adı sayar ve çözümler. Auth, kanal, kanal durumu ve lonca işareti bağlantıları bu adresle kurulur; karakter seçildikten sonraki bağlantı ise sunucunun bildirdiği adrese yapılır.
- Kanal portu sunucudaki hangi değerdir?
- O kanaldaki bir oyun çekirdeğinin CONFIG dosyasındaki PORT değeridir. P2P_PORT ya da DB_PORT yazılmaz. Karakter seçilince sunucu oyuncuyu zaten haritanın bulunduğu çekirdeğe yönlendirir.
- Kanallar giriş ekranında neden hep Bilinmeyen görünüyor?
- Durum bilgisi listedeki ilk kanalın adresinden istenir. O çekirdek kapalıysa ya da kanalların udp_port değeri çekirdeğin PORT değeriyle tutmuyorsa hiçbir kanalın durumu gelmez.
- Girişte sorun yok ama karakter seçince bağlantı kopuyor, neden?
- Karakter seçilince istemci, sunucunun o karakterin haritası için bildirdiği adrese bağlanır. Sunucu kendini iç ağ adresiyle tanıtıyorsa dışarıdaki oyuncular bu adrese ulaşamaz; CONFIG'de BIND_IP ya da PROXY_IP ile doğru adres verilmelidir.
İlgili sayfalar
- Metin2 Client Klasör Yapısı: Hangi Dosya Ne İşe Yarar? (Server kurma)
- Metin2 CONFIG Ayarları: Game Çekirdeği Seçenekleri ve Anlamları (Server kurma)
- Metin2 Açılmıyor ve İstemci Hataları: syserr.txt Nasıl Okunur? (Rehber)
- Metin2 Kanal ve Port Yapısı: auth, ch1, ch99 ve P2P (Server kurma)
- Metin2 Pack Dosyaları: EPK ve EIX Nedir? (Server kurma)
Kategori: Server Kurma Client (İstemci) istemci geliştirici kanal port serverinfo
Bu sayfadaki bilgiler Metin2'nin sunucu yazılımındaki hesaplamalara ve standart oyun dosyalarına dayanır. Oyun dosyalarını değiştiren sunucularda değerler farklı olabilir. İçerikleri nasıl hazırlıyoruz?