Windows Yuvaları: Bayt Sıralama
Bu makale ve iki yardımcı makale, Windows Yuvaları programlamadaki çeşitli sorunları açıklar. Bu makale bayt sıralamasını kapsar. Diğer sorunlar şu makalelerde ele alınmıştır: Windows Yuvaları: Engelleme ve Windows Yuvaları: Dizeleri Dönüştürme.
CAsyncSocket sınıfını kullanıyor veya sınıfından türetilirseniz, bu sorunları kendiniz yönetmeniz gerekir. CSocket sınıfını kullanır veya bu sınıftan türetilirseniz, MFC bunları sizin için yönetir.
Bayt Sıralama
Farklı makine mimarileri bazen verileri farklı bayt siparişlerini kullanarak depolar. Örneğin, Intel tabanlı makineler verileri Macintosh (Motorola) makinelerinin ters sırasına göre depolar. "little-Endian" olarak adlandırılan Intel bayt sırası aynı zamanda ağ standardı "big-Endian" sırasının tersidir. Aşağıdaki tabloda bu terimler açıklanmaktadır.
Big-and Little-Endian Byte Ordering
Bayt sıralama | Anlamı |
---|---|
Big-Endian | En önemli bayt bir sözcüğün sol ucundadır. |
Küçük Endian dili | En önemli bayt bir sözcüğün sağ ucundadır. |
Genellikle, ağ üzerinden gönderdiğiniz ve aldığınız veriler için bayt sırası dönüştürme konusunda endişelenmeniz gerekmez, ancak bayt siparişlerini dönüştürmeniz gereken durumlar vardır.
Bayt Siparişlerini Dönüştürmeniz Gerektiğinde
Aşağıdaki durumlarda bayt siparişlerini dönüştürmeniz gerekir:
Başka bir makineye gönderdiğiniz verilerin aksine ağ tarafından yorumlanması gereken bilgileri geçiriyorsunuz. Örneğin, ağın anlaması gereken bağlantı noktalarını ve adresleri geçirebilirsiniz.
İletişimde olduğunuz sunucu uygulaması bir MFC uygulaması değildir (ve bunun için kaynak kodunuz yoktur). Bu, iki makine aynı bayt sıralamasını paylaşmazsa bayt siparişi dönüştürmelerini çağırır.
Bayt Siparişlerini Dönüştürmeniz Gerekmediğinde
Aşağıdaki durumlarda bayt siparişlerini dönüştürme işinden kaçınabilirsiniz:
Her iki uçta bulunan makineler baytları değiştirmeme konusunda anlaşabilir ve her iki makine de aynı bayt sırasını kullanır.
İletişimde olduğunuz sunucu bir MFC uygulamasıdır.
İletişimde olduğunuz sunucu için kaynak kodunuz var, bu nedenle bayt siparişlerini dönüştürmeniz gerekip gerekmediğini açıkça anlayabilirsiniz.
Sunucuyu MFC'ye taşıyabilirsiniz. Bunu yapmak oldukça kolaydır ve sonuç genellikle daha küçük ve daha hızlı bir koddur.
CAsyncSocket ile çalışırken, gerekli bayt sırası dönüştürmelerini kendiniz yönetmeniz gerekir. Windows Yuvaları , "big-Endian" bayt sırası modelini standart hale getirir ve bu sıra ile diğerleri arasında dönüştürme işlevleri sağlar. Ancak CSocket ile kullandığınız CArchive, tam tersi ("little-Endian") sırasını kullanır, ancak CArchive
bayt sırası dönüştürmelerinin ayrıntılarını sizin için halleder. Uygulamalarınızda bu standart sıralamayı veya Windows Yuvaları bayt sırası dönüştürme işlevlerini kullanarak kodunuzu daha taşınabilir hale getirebilirsiniz.
MFC yuvalarını kullanmak için ideal durum, iletişimin her iki ucunu da yazdığınızdadır: her iki uçta da MFC kullanmak. FTP sunucusu gibi MFC olmayan uygulamalarla iletişim kuracak bir uygulama yazıyorsanız, windows yuvaları dönüştürme yordamları ntohs, ntohl, htons ve htonl kullanarak arşiv nesnesine veri geçirmeden önce bayt değiştirme işlemini yönetmeniz gerekebilir. Bu makalenin devamında MFC olmayan bir uygulamayla iletişim kurarken kullanılan bu işlevlerin bir örneği görüntülenir.
Dekont
İletişimin diğer ucu bir MFC uygulaması olmadığında, alıcı bunları işleyemeyeceğinden CObject
, arşivinize türetilen C++ nesnelerinin akışını yapmaktan da kaçınmanız gerekir. Windows Yuvaları: Yuvaları Arşivlerle Kullanma başlığı altındaki nota bakın.
Bayt siparişleri hakkında daha fazla bilgi için Bkz. Windows SDK'sında bulunan Windows Yuvaları belirtimi.
Bayt Sırası Dönüştürme Örneği
Aşağıdaki örnekte, arşiv kullanan bir CSocket
nesne için serileştirme işlevi gösterilmektedir. Ayrıca Windows Yuvaları API'sindeki bayt sırası dönüştürme işlevlerinin kullanılmasını da gösterir.
Bu örnek, kaynak koduna erişiminiz olmayan MFC olmayan bir sunucu uygulamasıyla iletişim kuran bir istemci yazdığınız bir senaryoyu sunar. Bu senaryoda, MFC olmayan sunucunun standart ağ bayt sırasını kullandığını varsaymalısınız. Buna karşılık, MFC istemci uygulamanız nesne içeren bir CArchive
CSocket
nesne kullanır ve CArchive
ağ standardının tam tersi olan "little-Endian" bayt sırasını kullanır.
İletişim kurmayı planladığınız MFC dışı sunucunun, aşağıdaki gibi bir ileti paketi için belirlenmiş bir protokole sahip olduğunu varsayalım:
struct Message
{
long MagicNumber;
unsigned short Command;
short Param1;
long Param2;
};
MFC açısından bu, aşağıdaki gibi ifade edilir:
struct Message
{
long m_lMagicNumber;
short m_nCommand;
short m_nParam1;
long m_lParam2;
void Serialize(CArchive &ar);
};
C++'ta , struct
temelde bir sınıfla aynıdır. Yapı, Message
yukarıda bildirilen üye işlevi gibi üye işlevlerine Serialize
sahip olabilir. Serialize
Üye işlevi şöyle görünebilir:
void Message::Serialize(CArchive &ar)
{
if (ar.IsStoring())
{
ar << (DWORD)htonl(m_lMagicNumber);
ar << (WORD)htons(m_nCommand);
ar << (WORD)htons(m_nParam1);
ar << (DWORD)htonl(m_lParam2);
}
else
{
WORD w;
DWORD dw;
ar >> dw;
m_lMagicNumber = ntohl((long)dw);
ar >> w;
m_nCommand = ntohs((short)w);
ar >> w;
m_nParam1 = ntohs((short)w);
ar >> dw;
m_lParam2 = ntohl((long)dw);
}
}
Bu örnekte, bir uçta MFC olmayan sunucu uygulamasının bayt sıralaması ile diğer uçtaki CArchive
MFC istemci uygulamanızda kullanılan arasında net bir uyuşmazlık olduğundan verilerin bayt sırası dönüştürmeleri çağrılır. Örnekte, Windows Yuvalarının sağladığı bayt sırası dönüştürme işlevlerinin birkaçı gösterilmektedir. Aşağıdaki tabloda bu işlevler açıklanmaktadır.
Windows Yuvaları Bayt Sırası Dönüştürme İşlevleri
Function | Purpose |
---|---|
ntohs | 16 bitlik bir miktarı ağ bayt siparişinden konak bayt siparişine dönüştürün (big-Endian'dan little-Endian'a). |
ntohl | 32 bitlik bir miktarı ağ bayt siparişinden konak bayt siparişine dönüştürün (big-Endian'dan little-Endian'a). |
Htons | 16 bitlik bir miktarı konak bayt siparişinden ağ bayt siparişine (little-Endian-big-Endian) dönüştürün. |
Htonl | 32 bitlik bir miktarı konak bayt siparişinden ağ bayt siparişine (little-Endian-big-Endian) dönüştürün. |
Bu örneğin bir diğer noktası, iletişimin diğer ucundaki yuva uygulaması MFC olmayan bir uygulama olduğunda aşağıdakine benzer bir işlem yapmaktan kaçınmanız gerektiğidir:
ar << pMsg;
burada pMsg
sınıfından CObject
türetilen bir C++ nesnesinin işaretçisidir. Bu işlem nesnelerle ilişkilendirilmiş ek MFC bilgileri gönderir ve sunucu bunu anlamayacaktır, MFC uygulamasıysa olduğu gibi.
Daha fazla bilgi için bkz.