青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

 在游戲服務器開發(fā)中, 網(wǎng)絡通信是很關鍵的, 而在網(wǎng)絡通信中,數(shù)據(jù)的同步是關鍵, 在我的上一篇博客(http://www.shnenglu.com/zhengxf/archive/2010/07/08/119737.html)中談的了數(shù)據(jù)如何同步的問題, 其中提到了兩點 1.數(shù)據(jù)發(fā)送給誰. 2.網(wǎng)絡延遲的話,如何同步.


    上次主要談了網(wǎng)絡延遲時的同步問題,今天我們主要談論數(shù)據(jù)發(fā)送給誰的問題, 要談論這個問題,我們就不的不談論: 地圖, NPC, 玩家他們?nèi)齻€之間的關系.

    其實地圖是個靜態(tài)的數(shù)據(jù)集合, 其中主要包含了地形信息和物品信息,這里的物品指的是靜態(tài)的,所以它是不需要進行同步的,也就是每個玩家在同一個地圖上看到信息是一樣的,所以這些信息有客戶端的場景管理器管理. 不進行網(wǎng)絡通信.

    NPC: NPC主要分兩種 一種是靜態(tài)的NPC,如玩家獲取任務的NPC, 另外玩家升級打的怪, 也是NPC.      靜態(tài)的NPC有屬性和功能,但不需要同步, 動態(tài)的NPC(如怪)需要進行網(wǎng)絡同步,這里我們就有一個問題, 動態(tài)的NPC要將它的信息發(fā)送給誰呢?任何一個涉及到網(wǎng)絡通信的NPC和玩家都有一個共同的性質(zhì)就是它有可見范圍,假如說一個玩家在十米范圍內(nèi)可見,那么他就回將信息發(fā)送給距離十米以內(nèi)的玩家和NPC, 這里有含有兩個問題: 一: 十米以外的NPC怎么辦, 二:怎么獲取十米以內(nèi)的發(fā)送用戶。有兩種解決辦法:一是在場景中搜索找到要發(fā)送的用戶信息,告訴服務器讓服務器來發(fā),二是發(fā)送自己的信息到服務器,服務器搜索NPC列表,和玩家列表,來發(fā)送,我覺的后著更合理。

   玩家: 玩家的同步主要是玩家和玩家的同步, 如玩家每前進一步, 就向服務器發(fā)一條消息. 服務器在玩家列表中查找到范圍之內(nèi)的其他玩家信息,并發(fā)送消息,這里有一個問題,是玩家要不要將消息發(fā)送給NPC?因為這種NPC也可以理解為機器人,它可以感知到敵人就在附近, 本身就在服務上, 所以不用發(fā)送消息, 但是NPC在感受到玩家的時候要向它(NPC) 可見范圍內(nèi)的玩家發(fā)送消息.

  接下來還有一個問題,是發(fā)送什么樣的消息的問題,因為針對NPC,和玩家,并不是所有的消息都發(fā),而是有選擇向的發(fā),這個問題我們下次討論。

posted @ 2010-09-03 12:28 鄭興鋒 閱讀(697) | 評論 (0)編輯 收藏

__stdcall和__cdecl兩者的區(qū)別;
#define CALLBACK __stdcall
#define WINAPI __stdcall
#define WINAPIV __cdecl
#define APIENTRY WINAPI
#define APIPRIVATE __stdcall
#define PASCAL __stdcall
#define cdecl _cdecl
#ifndef CDECL
#define CDECL _cdecl
#endif
幾乎我們寫的每一個WINDOWS API函數(shù)都是__stdcall類型的,首先,需要了解兩者之間的區(qū)別: WINDOWS的函數(shù)調(diào)用時需要用到棧(STACK,一種先入后出的存儲結(jié)構(gòu))。當函數(shù)調(diào)用完成后,棧需要清除,這里就是問題的關鍵,如何清除??如果我們的函數(shù)使用了_cdecl,那么棧的清除工作是由調(diào)用者,用COM的術語來講就是客戶來完成的。這樣帶來了一個棘手的問題,不同的編譯器產(chǎn)生棧的方式不盡相同,那么調(diào)用者能否正常的完成清除工作呢?答案是不能。如果使用__stdcall,上面的問題就解決了,函數(shù)自己解決清除工作。所以,在跨(開發(fā))平臺的調(diào)用中,我們都使用__stdcall(雖然有時是以 WINAPI的樣子出現(xiàn))。那么為什么還需要_cdecl呢?當我們遇到這樣的函數(shù)如fprintf()它的參數(shù)是可變的,不定長的,被調(diào)用者事先無法知道參數(shù)的長度,事后的清除工作也無法正常的進行,因此,這種情況我們只能使用_cdecl。到這里我們有一個結(jié)論,如果你的程序中沒有涉及可變參數(shù),最好使用__stdcall關鍵字。
2.
__cdecl,__stdcall是聲明的函數(shù)調(diào)用協(xié)議.主要是傳參和彈棧方面的不同.一般c++用的是__cdecl,windows里大都用的是__stdcall(API)
__cdecl 是C/C++和MFC程序默認使用的調(diào)用約定,也可以在函數(shù)聲明時加上__cdecl關鍵字來手工指定。采用__cdecl約定時,函數(shù)參數(shù)按照從右到左的順序入棧,并且由調(diào)用函數(shù)者把參數(shù)彈出棧以清理堆棧。因此,實現(xiàn)可變參數(shù)的函數(shù)只能使用該調(diào)用約定。由于每一個使用__cdecl約定的函數(shù)都要包含清理堆棧的代碼,所以產(chǎn)生的可執(zhí)行文件大小會比較大。__cdecl可以寫成_cdecl。
__stdcall調(diào)用約定用于調(diào)用Win32 API函數(shù)。采用__stdcall約定時,函數(shù)參數(shù)按照從右到左的順序入棧,被調(diào)用的函數(shù)在返回前清理傳送參數(shù)的棧,函數(shù)參數(shù)個數(shù)固定。由于函數(shù)體本身知道傳進來的參數(shù)個數(shù),因此被調(diào)用的函數(shù)可以在返回前用一條ret n指令直接清理傳遞參數(shù)的堆棧。__stdcall可以寫成_stdcall。
__fastcall 約定用于對性能要求非常高的場合。__fastcall約定將函數(shù)的從左邊開始的兩個大小不大于4個字節(jié)(DWORD)的參數(shù)分別放在ECX和EDX寄存器,其余的參數(shù)仍舊自右向左壓棧傳送,被調(diào)用的函數(shù)在返回前清理傳送參數(shù)的堆棧。__fastcall可以寫成_fastcall
3.
__stdcall:
_stdcall 調(diào)用約定相當于16位動態(tài)庫中經(jīng)常使用的PASCAL調(diào)用約定。
 
在32位的VC++5.0中PASCAL調(diào)用約定不再被支持(實際上它已被定義為 __stdcall。除了__pascal外,__fortran和__syscall也不被支持),取而代之的是__stdcall調(diào)用約定。兩者實質(zhì)上是一致的,即函數(shù)的參數(shù)自右向左通過棧傳遞,被調(diào)用的函數(shù)在返回前清理傳送參數(shù)的內(nèi)存棧,但不同的是函數(shù)名的修飾部分(關于函數(shù)名的修飾部分在后面將詳細說明)。
_stdcall是Pascal程序的缺省調(diào)用方式,通常用于Win32 Api中,函數(shù)采用從右到左的壓棧方式,自己在退出時清空堆棧。VC將函數(shù)編譯后會在函數(shù)名前面加上下劃線前綴,在函數(shù)名后加上"@"和參數(shù)的字節(jié)數(shù)。
_cdecl:
_cdecl c調(diào)用約定, 按從右至左的順序壓參數(shù)入棧,由調(diào)用者把參數(shù)彈出棧。對于傳送參數(shù)的內(nèi)存棧是由調(diào)用者來維護的(正因為如此,實現(xiàn)可變參數(shù)的函數(shù)只能使用該調(diào)用約定)。另外,在函數(shù)名修飾約定方面也有所不同。
_cdecl是C和C++程序的缺省調(diào)用方式。每一個調(diào)用它的函數(shù)都包含清空堆棧的代碼,所以產(chǎn)生的可執(zhí)行文件大小會比調(diào)用_stdcall函數(shù)的大。函數(shù)采用從右到左的壓棧方式。VC將函數(shù)編譯后會在函數(shù)名前面加上下劃線前綴。是MFC缺省調(diào)用約定。
__fastcall:
__fastcall調(diào)用約定是"人"如其名,它的主要特點就是快,因為它是通過寄存器來傳送參數(shù)的(實際上,它用ECX和EDX傳送前兩個雙字(DWORD)或更小的參數(shù),剩下的參數(shù)仍舊自右向左壓棧傳送,被調(diào)用的函數(shù)在返回前清理傳送參數(shù)的內(nèi)存棧),在函數(shù)名修飾約定方面,它和前兩者均不同。
_fastcall方式的函數(shù)采用寄存器傳遞參數(shù),VC將函數(shù)編譯后會在函數(shù)名前面加上"@"前綴,在函數(shù)名后加上"@"和參數(shù)的字節(jié)數(shù)。
thiscall:
thiscall僅僅應用于"C++"成員函數(shù)。this指針存放于CX寄存器,參數(shù)從右到左壓。thiscall不是關鍵詞,因此不能被程序員指定。
naked call:
采用1-4的調(diào)用約定時,如果必要的話,進入函數(shù)時編譯器會產(chǎn)生代碼來保存ESI,EDI,EBX,EBP寄存器,退出函數(shù)時則產(chǎn)生代碼恢復這些寄存器的內(nèi)容。
naked call不產(chǎn)生這樣的代碼。naked call不是類型修飾符,故必須和_declspec共同使用。
另附:
關鍵字 __stdcall、__cdecl和__fastcall可以直接加在要輸出的函數(shù)前,也可以在編譯環(huán)境的Setting...\C/C++ \Code Generation項選擇。當加在輸出函數(shù)前的關鍵字與編譯環(huán)境中的選擇不同時,直接加在輸出函數(shù)前的關鍵字有效。它們對應的命令行參數(shù)分別為/Gz、 /Gd和/Gr。缺省狀態(tài)為/Gd,即__cdecl。
要完全模仿PASCAL調(diào)用約定首先必須使用__stdcall調(diào)用約定,至于函數(shù)名修飾約定,可以通過其它方法模仿。還有一個值得一提的是WINAPI宏,Windows.h支持該宏,它可以將出函數(shù)翻譯成適當?shù)恼{(diào)用約定,在WIN32中,它被定義為__stdcall。使用WINAPI宏可以創(chuàng)建自己的APIs。
名字修飾約定
1、修飾名(Decoration name)
“C” 或者“C++”函數(shù)在內(nèi)部(編譯和鏈接)通過修飾名識別。修飾名是編譯器在編譯函數(shù)定義或者原型時生成的字符串。有些情況下使用函數(shù)的修飾名是必要的,如在模塊定義文件里頭指定輸出“C++”重載函數(shù)、構(gòu)造函數(shù)、析構(gòu)函數(shù),又如在匯編代碼里調(diào)用“C””或“C++”函數(shù)等。
修飾名由函數(shù)名、類名、調(diào)用約定、返回類型、參數(shù)等共同決定。
2、名字修飾約定隨調(diào)用約定和編譯種類(C或C++)的不同而變化。函數(shù)名修飾約定隨編譯種類和調(diào)用約定的不同而不同,下面分別說明。
a、C編譯時函數(shù)名修飾約定規(guī)則:
__stdcall調(diào)用約定在輸出函數(shù)名前加上一個下劃線前綴,后面加上一個“@”符號和其參數(shù)的字節(jié)數(shù),格式為_functionname@number
__cdecl調(diào)用約定僅在輸出函數(shù)名前加上一個下劃線前綴,格式為_functionname。
__fastcall調(diào)用約定在輸出函數(shù)名前加上一個“@”符號,后面也是一個“@”符號和其參數(shù)的字節(jié)數(shù),格式為@functionname@number。
它們均不改變輸出函數(shù)名中的字符大小寫,這和PASCAL調(diào)用約定不同,PASCAL約定輸出的函數(shù)名無任何修飾且全部大寫。
b、C++編譯時函數(shù)名修飾約定規(guī)則:
__stdcall調(diào)用約定:
1、以“?”標識函數(shù)名的開始,后跟函數(shù)名;
2、函數(shù)名后面以“@@YG”標識參數(shù)表的開始,后跟參數(shù)表;
3、參數(shù)表以代號表示:
X--void ,
D--char,
E--unsigned char,
F--short,
H--int,
I--unsigned int,
J--long,
K--unsigned long,
M--float,
N--double,
_N--bool,
....
PA--表示指針,后面的代號表明指針類型,如果相同類型的指針連續(xù)出現(xiàn),以“0”代替,一個“0”代表一次重復;
4、參數(shù)表的第一項為該函數(shù)的返回值類型,其后依次為參數(shù)的數(shù)據(jù)類型,指針標識在其所指數(shù)據(jù)類型前;
5、參數(shù)表后以“@Z”標識整個名字的結(jié)束,如果該函數(shù)無參數(shù),則以“Z”標識結(jié)束。
其格式為“?functionname@@YG*****@Z”或“?functionname@@YG*XZ”,例如
int Test1(char *var1,unsigned long)-----“?Test1@@YGHPADK@Z
void Test2() -----“?Test2@@YGXXZ
__cdecl調(diào)用約定:
規(guī)則同上面的_stdcall調(diào)用約定,只是參數(shù)表的開始標識由上面的“@@YG”變?yōu)?a href="mailto:“@@YA">“@@YA”。
__fastcall調(diào)用約定:
規(guī)則同上面的_stdcall調(diào)用約定,只是參數(shù)表的開始標識由上面的“@@YG”變?yōu)?a href="mailto:“@@YI">“@@YI”。
VC++對函數(shù)的省缺聲明是“__cedcl“,將只能被C/C++調(diào)用.
CB在輸出函數(shù)聲明時使用4種修飾符號
//__cdecl
cb的默認值,它會在輸出函數(shù)名前加_,并保留此函數(shù)名不變,參數(shù)按照從右到左的順序依次傳遞給棧,也可以寫成_cdecl和cdecl形式。
//__fastcall
她修飾的函數(shù)的參數(shù)將盡肯呢感地使用寄存器來處理,其函數(shù)名前加@,參數(shù)按照從左到右的順序壓棧;
//__pascal
它說明的函數(shù)名使用Pascal格式的命名約定。這時函數(shù)名全部大寫。參數(shù)按照從左到右的順序壓棧;
//__stdcall
使用標準約定的函數(shù)名。函數(shù)名不會改變。使用__stdcall修飾時。參數(shù)按照由右到左的順序壓棧,也可以是_stdcall;
VC++對函數(shù)的省缺聲明是"__cedcl",將只能被C/C++調(diào)用.
 
注意:
1、_beginthread需要__cdecl的線程函數(shù)地址,_beginthreadex和CreateThread需要__stdcall的線程函數(shù)地址。
2、一般WIN32的函數(shù)都是__stdcall。而且在Windef.h中有如下的定義:
 #define CALLBACK __stdcall
 #define WINAPI  __stdcall
3、extern "C" _declspec(dllexport) int __cdecl Add(int a, int b);
   typedef int (__cdecl*FunPointer)(int a, int b);
   修飾符的書寫順序如上。
4、extern "C"的作用:如果Add(int a, int b)是在c語言編譯器編譯,而在c++文件使用,則需要在c++文件中聲明:extern "C" Add(int a, int b),因為c編譯器和c++編譯器對函數(shù)名的解釋不一樣(c++編譯器解釋函數(shù)名的時候要考慮函數(shù)參數(shù),這樣是了方便函數(shù)重載,而在c語言中不存在函數(shù)重載的問題),使用extern "C",實質(zhì)就是告訴c++編譯器,該函數(shù)是c庫里面的函數(shù)。如果不使用extern "C"則會出現(xiàn)鏈接錯誤。
一般象如下使用:
#ifdef _cplusplus
#define EXTERN_C extern "C"
#else
#define EXTERN_C extern
#endif
#ifdef _cplusplus
extern "C"{
#endif
 EXTERN_C int func(int a, int b);
#ifdef _cplusplus
}
#endif
5、MFC提供了一些宏,可以使用AFX_EXT_CLASS來代替__declspec(DLLexport),并修飾類名,從而導出類,AFX_API_EXPORT來修飾函數(shù),AFX_DATA_EXPORT來修飾變量
AFX_CLASS_IMPORT:__declspec(DLLexport)
AFX_API_IMPORT:__declspec(DLLexport)
AFX_DATA_IMPORT:__declspec(DLLexport)
AFX_CLASS_EXPORT:__declspec(DLLexport)
AFX_API_EXPORT:__declspec(DLLexport)
AFX_DATA_EXPORT:__declspec(DLLexport)
AFX_EXT_CLASS:#ifdef _AFXEXT
   AFX_CLASS_EXPORT
        #else
   AFX_CLASS_IMPORT
6、DLLMain負責初始化(Initialization)和結(jié)束 (Termination)工作,每當一個新的進程或者該進程的新的線程訪問DLL時,或者訪問DLL的每一個進程或者線程不再使用DLL或者結(jié)束時,都會調(diào)用DLLMain。但是,使用TerminateProcess或TerminateThread結(jié)束進程或者線程,不會調(diào)用DLLMain。
7、一個DLL在內(nèi)存中只有一個實例
DLL程序和調(diào)用其輸出函數(shù)的程序的關系:
1)、DLL與進程、線程之間的關系
DLL模塊被映射到調(diào)用它的進程的虛擬地址空間。
DLL使用的內(nèi)存從調(diào)用進程的虛擬地址空間分配,只能被該進程的線程所訪問。
DLL的句柄可以被調(diào)用進程使用;調(diào)用進程的句柄可以被DLL使用。
DLLDLL可以有自己的數(shù)據(jù)段,但沒有自己的堆棧,使用調(diào)用進程的棧,與調(diào)用它的應用程序相同的堆棧模式。
2)、關于共享數(shù)據(jù)段
DLL定義的全局變量可以被調(diào)用進程訪問;DLL可以訪問調(diào)用進程的全局數(shù)據(jù)。使用同一 DLL的每一個進程都有自己的DLL全局變量實例。如果多個線程并發(fā)訪問同一變量,則需要使用同步機制;對一個DLL的變量,如果希望每個使用DLL的線程都有自己的值,則應該使用線程局部存儲(TLS,Thread Local Strorage)。

posted @ 2010-08-30 10:36 鄭興鋒 閱讀(1663) | 評論 (0)編輯 收藏

于網(wǎng)絡所帶來的諸多不安全因素使得網(wǎng)絡使用者不得不采取相應的網(wǎng)絡安全對策。為了堵塞安全漏洞和提供安全的通信服務,必須運用一定的技術來對網(wǎng)絡進行安全建設,這已為廣大網(wǎng)絡開發(fā)商和網(wǎng)絡用戶所共識。

現(xiàn)今主要的網(wǎng)絡安全技術有以下幾種:

一、加密路由器(Encrypting Router)技術

加密路由器把通過路由器的內(nèi)容進行加密和壓縮,然后讓它們通過不安全的網(wǎng)絡進行傳輸,并在目的端進行解壓和解密。

二、安全內(nèi)核(Secured Kernel)技術

人們開始在操作系統(tǒng)的層次上考慮安全性,嘗試把系統(tǒng)內(nèi)核中可能引起安全性問題的部分從內(nèi)核中剔除出去,從而使系統(tǒng)更安全。如S olaris操作系統(tǒng)把靜態(tài)的口令放在一個隱含文件中, 使系統(tǒng)的安全性增強。

三、網(wǎng)絡地址轉(zhuǎn)換器(Network Address Translater)

網(wǎng)絡地址轉(zhuǎn)換器也稱為地址共享器(Address Sharer)或地址映射器,初衷是為了解決IP 地址不足,現(xiàn)多用于網(wǎng)絡安全。內(nèi)部主機向外部主機連接時,使用同一個IP地址;相反地,外部主機要向內(nèi)部主機連接時,必須通過網(wǎng)關映射到內(nèi)部主機上。它使外部網(wǎng)絡看不到內(nèi)部網(wǎng)絡, 從而隱藏內(nèi)部網(wǎng)絡,達到保密作用。

數(shù)據(jù)加密(Data Encryption)技術

所謂加密(Encryption)是指將一個信息(或稱明文--plaintext) 經(jīng)過加密鑰匙(Encrypt ionkey)及加密函數(shù)轉(zhuǎn)換,變成無意義的密文( ciphertext),而接收方則將此密文經(jīng)過解密函數(shù)、解密鑰匙(Decryti on key)還原成明文。加密技術是網(wǎng)絡安全技術的基石。

數(shù)據(jù)加密技術要求只有在指定的用戶或網(wǎng)絡下,才能解除密碼而獲得原來的數(shù)據(jù),這就需要給數(shù)據(jù)發(fā)送方和接受方以一些特殊的信息用于加解密,這就是所謂的密鑰。其密鑰的值是從大量的隨機數(shù)中選取的。按加密算法分為專用密鑰和公開密鑰兩種。

專用密鑰,又稱為對稱密鑰或單密鑰,加密時使用同一個密鑰,即同一個算法。如DES和MIT的Kerberos算法。單密鑰是最簡單方式,通信雙方必須交換彼此密鑰,當需給對方發(fā)信息時,用自己的加密密鑰進行加密,而在接收方收到數(shù)據(jù)后,用對方所給的密鑰進行解密。這種方式在與多方通信時因為需要保存很多密鑰而變得很復雜,而且密鑰本身的安全就是一個問題。

DES是一種數(shù)據(jù)分組的加密算法,它將數(shù)據(jù)分成長度為6 4位的數(shù)據(jù)塊,其中8位用作奇偶校驗,剩余的56位作為密碼的長度。第一步將原文進行置換,得到6 4位的雜亂無章的數(shù)據(jù)組;第二步將其分成均等兩段 ;第三步用加密函數(shù)進行變換,并在給定的密鑰參數(shù)條件下,進行多次迭代而得到加密密文。

公開密鑰,又稱非對稱密鑰,加密時使用不同的密鑰,即不同的算法,有一把公用的加密密鑰,有多把解密密鑰,如RSA算法。

在計算機網(wǎng)絡中,加密可分為"通信加密"(即傳輸過程中的數(shù)據(jù)加密)和"文件加密"(即存儲數(shù)據(jù)加密)。通信加密又有節(jié)點加密、鏈路加密和端--端加密3種。

①節(jié)點加密,從時間坐標來講,它在信息被傳入實際通信連接點 (Physical communication link)之前進行;從OSI 7層參考模型的坐標 (邏輯空間)來講,它在第一層、第二層之間進行; 從實施對象來講,是對相鄰兩節(jié)點之間傳輸?shù)臄?shù)據(jù)進行加密,不過它僅對報文加密,而不對報頭加密,以便于傳輸路由的選擇。

②鏈路加密(Link Encryption),它在數(shù)據(jù)鏈路層進行,是對相鄰節(jié)點之間的鏈路上所傳輸?shù)臄?shù)據(jù)進行加密,不僅對數(shù)據(jù)加密還對報頭加密。

③端--端加密(End-to-End Encryption),它在第六層或第七層進行 ,是為用戶之間傳送數(shù)據(jù)而提供的連續(xù)的保護。在始發(fā)節(jié)點上實施加密,在中介節(jié)點以密文形式傳輸,最后到達目的節(jié)點時才進行解密,這對防止拷貝網(wǎng)絡軟件和軟件泄漏也很有效。

在OSI參考模型中,除會話層不能實施加密外,其他各層都可以實施一定的加密措施。但通常是在最高層上加密,即應用層上的每個應用都被密碼編碼進行修改,因此能對每個應用起到保密的作用,從而保護在應用層上的投資。假如在下面某一層上實施加密,如TCP層上,就只能對這層起到保護作用。

值得注意的是,能否切實有效地發(fā)揮加密機制的作用,關鍵的問題在于密鑰的管理,包括密鑰的生存、分發(fā)、安裝、保管、使用以及作廢全過程。

(1)數(shù)字簽名

公開密鑰的加密機制雖提供了良好的保密性,但難以鑒別發(fā)送者, 即任何得到公開密鑰的人都可以生成和發(fā)送報文。數(shù)字簽名機制提供了一種鑒別方法,以解決偽造、抵賴、冒充和篡改等問題。

數(shù)字簽名一般采用不對稱加密技術(如RSA),通過對整個明文進行某種變換,得到一個值,作為核實簽名。接收者使用發(fā)送者的公開密鑰對簽名進行解密運算,如其結(jié)果為明文,則簽名有效,證明對方的身份是真實的。當然,簽名也可以采用多種方式,例如,將簽名附在明文之后。數(shù)字簽名普遍用于銀行、電子貿(mào)易等。

數(shù)字簽名不同于手寫簽字:數(shù)字簽名隨文本的變化而變化,手寫簽字反映某個人個性特征, 是不變的;數(shù)字簽名與文本信息是不可分割的,而手寫簽字是附加在文本之后的,與文本信息是分離的。

(2)Kerberos系統(tǒng)

Kerberos系統(tǒng)是美國麻省理工學院為Athena工程而設計的,為分布式計算環(huán)境提供一種對用戶雙方進行驗證的認證方法。

它的安全機制在于首先對發(fā)出請求的用戶進行身份驗證,確認其是否是合法的用戶;如是合法的用戶,再審核該用戶是否有權對他所請求的服務或主機進行訪問。從加密算法上來講,其驗證是建立在對稱加密的基礎上的。

Kerberos系統(tǒng)在分布式計算環(huán)境中得到了廣泛的應用(如在Notes 中),這是因為它具有如下的特點:

①安全性高,Kerberos系統(tǒng)對用戶的口令進行加密后作為用戶的私鑰,從而避免了用戶的口令在網(wǎng)絡上顯示傳輸,使得竊聽者難以在網(wǎng)絡上取得相應的口令信息;

②透明性高,用戶在使用過程中,僅在登錄時要求輸入口令,與平常的操作完全一樣,Ker beros的存在對于合法用戶來說是透明的;

③可擴展性好,Kerberos為每一個服務提供認證,確保應用的安全。

Kerberos系統(tǒng)和看電影的過程有些相似,不同的是只有事先在Ker beros系統(tǒng)中登錄的客戶才可以申請服務,并且Kerberos要求申請到入場券的客戶就是到TGS(入場券分配服務器)去要求得到最終服務的客戶。
Kerberos的認證協(xié)議過程如圖二所示。

Kerberos有其優(yōu)點,同時也有其缺點,主要如下:

①、Kerberos服務器與用戶共享的秘密是用戶的口令字,服務器在回應時不驗證用戶的真實性,假設只有合法用戶擁有口令字。如攻擊者記錄申請回答報文,就易形成代碼本攻擊。

②、Kerberos服務器與用戶共享的秘密是用戶的口令字,服務器在回應時不驗證用戶的真實性,假設只有合法用戶擁有口令字。如攻擊者記錄申請回答報文,就易形成代碼本攻擊。

③、AS和TGS是集中式管理,容易形成瓶頸,系統(tǒng)的性能和安全也嚴重依賴于AS和TGS的性能和安全。在AS和TGS前應該有訪問控制,以增強AS和TGS的安全。

④、隨用戶數(shù)增加,密鑰管理較復雜。Kerberos擁有每個用戶的口令字的散列值,AS與TGS 負責戶間通信密鑰的分配。當N個用戶想同時通信時,仍需要N*(N-1)/2個密鑰

( 3 )、PGP算法

PGP(Pretty Good Privacy)是作者hil Zimmermann提出的方案, 從80年代中期開始編寫的。公開密鑰和分組密鑰在同一個系統(tǒng)中,公開密鑰采用RSA加密算法,實施對密鑰的管理;分組密鑰采用了IDEA算法,實施對信息的加密。

PGP應用程序的第一個特點是它的速度快,效率高;另一個顯著特點就是它的可移植性出色,它可以在多種操作平臺上運行。PGP主要具有加密文件、發(fā)送和接收加密的E-mail、數(shù)字簽名等。

(4)、PEM算法

保密增強郵件(Private Enhanced Mail,PEM),是美國RSA實驗室基于RSA和DES算法而開發(fā)的產(chǎn)品,其目的是為了增強個人的隱私功能, 目前在Internet網(wǎng)上得到了廣泛的應用,專為E-mail用戶提供如下兩類安全服務:

對所有報文都提供諸如:驗證、完整性、防抵 賴等安全服務功能; 提供可選的安全服務功能,如保密性等。

PEM對報文的處理經(jīng)過如下過程:

第一步,作規(guī)范化處理:為了使PEM與MTA(報文傳輸代理)兼容,按S MTP協(xié)議對報文進行規(guī)范化處理;

第二步,MIC(Message Integrity Code)計算;

第三步,把處理過的報文轉(zhuǎn)化為適于SMTP系統(tǒng)傳輸?shù)母袷健?

身份驗證技術

身份識別(Identification)是指定用戶向系統(tǒng)出示自己的身份證明過程。身份認證(Authertication)是系統(tǒng)查核用戶的身份證明的過程。人們常把這兩項工作統(tǒng)稱為身份驗證(或身份鑒別),是判明和確認通信雙方真實身份的兩個重要環(huán)節(jié)。

Web網(wǎng)上采用的安全技術

在Web網(wǎng)上實現(xiàn)網(wǎng)絡安全一般有SHTTP/HTTP和SSL兩種方式。

(一)、SHTTP/HTTP

SHTTP/HTTP可以采用多種方式對信息進行封裝。封裝的內(nèi)容包括加密、簽名和基于MAC 的認證。并且一個消息可以被反復封裝加密。此外,SHTTP還定義了包頭信息來進行密鑰傳輸、認證傳輸和相似的管理功能。SHTTP可以支持多種加密協(xié)議,還為程序員提供了靈活的編程環(huán)境。

SHTTP并不依賴于特定的密鑰證明系統(tǒng),它目前支持RSA、帶內(nèi)和帶外以及Kerberos密鑰交換。

(二)、SSL(安全套層) 安全套接層是一種利用公開密鑰技術的工業(yè)標準。SSL廣泛應用于Intranet和Internet 網(wǎng),其產(chǎn)品包括由Netscape、Microsoft、IBM 、Open Market等公司提供的支持SSL的客戶機和服務器,以及諸如Apa che-SSL等產(chǎn)品。

SSL提供三種基本的安全服務,它們都使用公開密鑰技術。

①信息私密,通過使用公開密鑰和對稱密鑰技術以達到信息私密。SSL客戶機和SSL服務器之間的所有業(yè)務使用在SSL握手過程中建立的密鑰和算法進行加密。這樣就防止了某些用戶通過使用IP packet sniffer工具非法竊聽。盡管packet sniffer仍能捕捉到通信的內(nèi)容, 但卻無法破譯。 ②信息完整性,確保SSL業(yè)務全部達到目的。如果Internet成為可行的電子商業(yè)平臺,應確保服務器和客戶機之間的信息內(nèi)容免受破壞。SSL利用機密共享和hash函數(shù)組提供信息完整性服務。③相互認證,是客戶機和服務器相互識別的過程。它們的識別號用公開密鑰編碼,并在SSL握手時交換各自的識別號。為了驗證證明持有者是其合法用戶(而不是冒名用戶),SSL要求證明持有者在握手時對交換數(shù)據(jù)進行數(shù)字式標識。證明持有者對包括證明的所有信息數(shù)據(jù)進行標識以說明自己是證明的合法擁有者。這樣就防止了其他用戶冒名使用證明。證明本身并不提供認證,只有證明和密鑰一起才起作用。 ④SSL的安全性服務對終端用戶來講做到盡可能透明。一般情況下,用戶只需單擊桌面上的一個按鈕或聯(lián)接就可以與SSL的主機相連。與標準的HTTP連接申請不同,一臺支持SSL的典型網(wǎng)絡主機接受SSL連接的默認端口是443而不是80。

當客戶機連接該端口時,首先初始化握手協(xié)議,以建立一個SSL對話時段。握手結(jié)束后,將對通信加密,并檢查信息完整性,直到這個對話時段結(jié)束為止。每個SSL對話時段只發(fā)生一次握手。相比之下,HTTP 的每一次連接都要執(zhí)行一次握手,導致通信效率降低。一次SSL握手將發(fā)生以下事件:

1.客戶機和服務器交換X.509證明以便雙方相互確認。這個過程中可以交換全部的證明鏈,也可以選擇只交換一些底層的證明。證明的驗證包括:檢驗有效日期和驗證證明的簽名權限。

2.客戶機隨機地產(chǎn)生一組密鑰,它們用于信息加密和MAC計算。這些密鑰要先通過服務器的公開密鑰加密再送往服務器。總共有四個密鑰分別用于服務器到客戶機以及客戶機到服務器的通信。

3.信息加密算法(用于加密)和hash函數(shù)(用于確保信息完整性)是綜合在一起使用的。Netscape的SSL實現(xiàn)方案是:客戶機提供自己支持的所有算法清單,服務器選擇它認為最有效的密碼。服務器管理者可以使用或禁止某些特定的密碼。

代理服務

在 Internet 中廣泛采用代理服務工作方式, 如域名系統(tǒng)(DNS), 同時也有許多人把代理服務看成是一種安全性能。

從技術上來講代理服務(Proxy Service)是一種網(wǎng)關功能,但它的邏輯位置是在OSI 7層協(xié)議的應用層之上。

代理(Proxy)使用一個客戶程序,與特定的中間結(jié)點鏈接,然后中間結(jié)點與期望的服務器進行實際鏈接。與應用網(wǎng)關型防火墻所不同的是,使用這類防火墻時外部網(wǎng)絡與內(nèi)部網(wǎng)絡之間不存在直接連接,因此 ,即使防火墻產(chǎn)生了問題,外部網(wǎng)絡也無法與被保護的網(wǎng)絡連接。

防火墻技術

(1)防火墻的概念

在計算機領域,把一種能使一個網(wǎng)絡及其資源不受網(wǎng)絡"墻"外"火災"影響的設備稱為"防火墻"。用更專業(yè)一點的話來講,防火墻(FireW all)就是一個或一組網(wǎng)絡設備(計算機系統(tǒng)或路由器等),用來在兩個或多個網(wǎng)絡間加強訪問控制,其目的是保護一個網(wǎng)絡不受來自另一個網(wǎng)絡的攻擊。可以這樣理解,相當于在網(wǎng)絡周圍挖了一條護城河,在唯一的橋上設立了安全哨所,進出的行人都要接受安全檢查。

防火墻的組成可以這樣表示:防火墻=過濾器+安全策略(+網(wǎng)關)。

(2)防火墻的實現(xiàn)方式

①在邊界路由器上實現(xiàn);
②在一臺雙端口主機(dual-homed host)上實現(xiàn);
③在公共子網(wǎng)(該子網(wǎng)的作用相當于一臺雙端口主機)上實現(xiàn),在此子網(wǎng)上可建立含有停火區(qū)結(jié)構(gòu)的防火墻。

(3)防火墻的網(wǎng)絡結(jié)構(gòu)

網(wǎng)絡的拓撲結(jié)構(gòu)和防火墻的合理配置與防火墻系統(tǒng)的性能密切相關,防火墻一般采用如下幾種結(jié)構(gòu)。
①最簡單的防火墻結(jié)構(gòu)
這種網(wǎng)絡結(jié)構(gòu)能夠達到使受保護的網(wǎng)絡只能看到"橋頭堡主機"( 進出通信必經(jīng)之主機), 同時,橋頭堡主機不轉(zhuǎn)發(fā)任何TCP/IP通信包, 網(wǎng)絡中的所有服務都必須有橋頭堡主機的相應代理服務程序來支持。但它把整個網(wǎng)絡的安全性能全部托付于其中的單個安全單元,而單個網(wǎng)絡安全單元又是攻擊者首選的攻擊對象,防火墻一旦破壞,橋頭堡主機就變成了一臺沒有尋徑功能的路由器,系統(tǒng)的安全性不可靠。

②單網(wǎng)端防火墻結(jié)構(gòu)

其中屏蔽路由器的作用在于保護堡壘主機(應用網(wǎng)關或代理服務) 的安全而建立起一道屏障。在這種結(jié)構(gòu)中可將堡壘主機看作是信息服務器,它是內(nèi)部網(wǎng)絡對外發(fā)布信息的數(shù)據(jù)中心,但這種網(wǎng)絡拓撲結(jié)構(gòu)仍把網(wǎng)絡的安全性大部分托付給屏蔽路由器。系統(tǒng)的安全性仍不十分可靠。

③增強型單網(wǎng)段防火墻的結(jié)構(gòu)

為增強網(wǎng)段防火墻安全性,在內(nèi)部網(wǎng)與子網(wǎng)之間增設一臺屏蔽路由器,這樣整個子網(wǎng)與內(nèi)外部網(wǎng)絡的聯(lián)系就各受控于一個工作在網(wǎng)絡級的路由器,內(nèi)部網(wǎng)絡與外部網(wǎng)絡仍不能直接聯(lián)系,只能通過相應的路由器與堡壘主機通信。

④含"停火區(qū)"的防火墻結(jié)構(gòu)

針對某些安全性特殊需要, 可建立如下的防火墻網(wǎng)絡結(jié)構(gòu)。 網(wǎng)絡的整個安全特性分擔到多個安全單元, 在外停火區(qū)的子網(wǎng)上可聯(lián)接公共信息服務器,作為內(nèi)外網(wǎng)絡進行信息交換的場所。

網(wǎng)絡反病毒技術

由于在網(wǎng)絡環(huán)境下,計算機病毒具有不可估量的威脅性和破壞力, 因此計算機病毒的防范也是網(wǎng)絡安全性建設中重要的一環(huán)。網(wǎng)絡反病毒技術也得到了相應的發(fā)展。

網(wǎng)絡反病毒技術包括預防病毒、檢測病毒和消毒等3種技術。(1) 預防病毒技術,它通過自身常駐系統(tǒng)內(nèi)存,優(yōu)先獲得系統(tǒng)的控制權,監(jiān)視和判斷系統(tǒng)中是否有病毒存在,進而阻止計算機病毒進入計算機系統(tǒng)和對系統(tǒng)進行破壞。這類技術是:加密可執(zhí)行程序、引導區(qū)保護、系統(tǒng)監(jiān)控與讀寫控制(如防病毒卡)等。(2)檢測病毒技術,它是通過對計算機病毒的特征來進行判斷的技術,如自身校驗、關鍵字、文件長度的變化等。(3)消毒技術,它通過對計算機病毒的分析,開發(fā)出具有刪除病毒程序并恢復原文件的軟件。

網(wǎng)絡反病毒技術的實施對象包括文件型病毒、引導型病毒和網(wǎng)絡病毒。

網(wǎng)絡反病毒技術的具體實現(xiàn)方法包括對網(wǎng)絡服務器中的文件進行頻繁地掃描和監(jiān)測;在工作站上采用防病毒芯片和對網(wǎng)絡目錄及文件設置訪問權限等。

隨著網(wǎng)上應用不斷發(fā)展,網(wǎng)絡技術不斷應用,網(wǎng)絡不安全因素將會不斷產(chǎn)生,但互為依存的,網(wǎng)絡安全技術也會迅速的發(fā)展,新的安全技術將會層出不窮,最終Internet網(wǎng)上的安全問題將不會阻擋我們前進的步伐

posted @ 2010-08-02 11:33 鄭興鋒 閱讀(513) | 評論 (0)編輯 收藏

在網(wǎng)絡游戲中,會涉及到數(shù)據(jù)傳送,所以就有一個要解決的問題,如何定義數(shù)據(jù)包格式,就目前我所知道的數(shù)據(jù)定義方式描述一下,歡迎各位高手指點,
第一種方式:
定義數(shù)據(jù)頭:
//網(wǎng)絡包頭
typedef struct PacketHeader
{
 byte  id[4];  //u_int32 lb
 byte  len[4];  //u_int32 lb
 byte  version[2]; //u_int16 lb
 byte  type[2];  //u_int16 lb 

}PacketHeader;

定義數(shù)據(jù)體:
//網(wǎng)絡數(shù)據(jù)包體
class CPackage
{
public:
 CPackage(void);
 //CPackage(byte* pParam, int nLen);
 ~CPackage(void);
public:
 u_int16 GetType();
 void SetType(u_int16 nType);
 DWORD GetLen();
 void SetLen(int nLen);
 tstring GetContent();
 void SetContent(tstring strContent);
 virtual void* GetPackage();
 void SetBuf(byte* pParam);
 virtual byte*   GetBuf(u_int32 nLen);
protected:
 u_int16  m_nType;
 int   m_nLen;  //這里數(shù)據(jù)長度代表的是,長度以后要取的字節(jié)的個數(shù)
 tstring   m_strContent;
 tstring   m_strBuf;
 byte*   m_pBuf;
 PacketHeader m_pHeader;
};
在數(shù)據(jù)包里面包含 包頭, 用函數(shù)來實現(xiàn)對包頭和包內(nèi)容的操作。
第二種定義方式:
//網(wǎng)絡包頭
typedef struct PacketHeader
{
 byte  id[4];  //u_int32 lb
 byte  len[4];  //u_int32 lb
 byte  version[2]; //u_int16 lb
 byte  type[2];  //u_int16 lb 

}PacketHeader;

定義數(shù)據(jù)體:
//網(wǎng)絡數(shù)據(jù)包體
class CPackage: public PacketHeader
{
public:
 CPackage(void);
 //CPackage(byte* pParam, int nLen);
 ~CPackage(void);
public:
 u_int16 GetType();
 void SetType(u_int16 nType);
 DWORD GetLen();
 void SetLen(int nLen);
 tstring GetContent();
 void SetContent(tstring strContent);
 virtual void* GetPackage();
 void SetBuf(byte* pParam);
 virtual byte*   GetBuf(u_int32 nLen);
protected:
 u_int16  m_nType;
 int   m_nLen;  //這里數(shù)據(jù)長度代表的是,長度以后要取的字節(jié)的個數(shù)
 tstring   m_strContent;
 tstring   m_strBuf;
 byte*   m_pBuf;
};

這兩種方式的區(qū)別,就是一個用包含包頭,一個用派生。歡迎有更好解決辦法的朋友寫出來分享一下.

posted @ 2010-07-19 11:31 鄭興鋒 閱讀(629) | 評論 (0)編輯 收藏

 同步在網(wǎng)絡游戲中是非常重要的,它保證了每個玩家在屏幕上看到的東西大體是一樣的。其實呢,解決同步問題的最簡單的方法就是把每個玩家的動作都向其他玩家廣播一遍,這里其實就存在兩個問題:1,向哪些玩家廣播,廣播哪些消息。2,如果網(wǎng)絡延遲怎么辦。事實上呢,第一個問題是個非常簡單的問題,不過之所以我提出這個問題來,是提醒大家在設計自己的消息結(jié)構(gòu)的時候,需要把這個因素考慮進去。而對于第二個問題,則是一個挺麻煩的問題,大家可以來看這么個例子:

  比如有一個玩家A向服務器發(fā)了條指令,說我現(xiàn)在在P1點,要去P2點。指令發(fā)出的時間是T0,服務器收到指令的時間是T1,然后向周圍的玩家廣播這條消息,消息的內(nèi)容是“玩家A從P1到P2”有一個在A附近的玩家B,收到服務器的這則廣播的消息的時間是T2,然后開始在客戶端上畫圖,A從P1到P2點。這個時候就存在一個不同步的問題,玩家A和玩家B的屏幕上顯示的畫面相差了T2-T1的時間。這個時候怎么辦呢?

  有個解決方案,我給它取名叫 預測拉扯,雖然有些怪異了點,不過基本上大家也能從字面上來理解它的意思。要解決這個問題,首先要定義一個值叫:預測誤差。然后需要在服務器端每個玩家連接的類里面加一項屬性,叫TimeModified,然后在玩家登陸的時候,對客戶端的時間和服務器的時間進行比較,得出來的差值保存在TimeModified里面。還是上面的那個例子,服務器廣播消息的時候,就根據(jù)要廣播對象的TimeModified,計算出一個客戶端的CurrentTime,然后在消息頭里面包含這個CurrentTime,然后再進行廣播。并且同時在玩家A的客戶端本地建立一個隊列,保存該條消息,只到獲得服務器驗證就從未被驗證的消息隊列里面將該消息刪除,如果驗證失敗,則會被拉扯回P1點。然后當玩家B收到了服務器發(fā)過來的消息“玩家A從P1到P2”這個時候就檢查消息里面服務器發(fā)出的時間和本地時間做比較,如果大于定義的預測誤差,就算出在T2這個時間,玩家A的屏幕上走到的地點P3,然后把玩家B屏幕上的玩家A直接拉扯到P3,再繼續(xù)走下去,這樣就能保證同步。更進一步,為了保證客戶端運行起來更加smooth,我并不推薦直接把玩家拉扯過去,而是算出P3偏后的一點P4,然后用(P4-P1)/T(P4-P3)來算出一個很快的速度S,然后讓玩家A用速度S快速移動到P4,這樣的處理方法是比較合理的,這種解決方案的原形在國際上被稱為(Full plesiochronous),當然,該原形被我篡改了很多來適應網(wǎng)絡游戲的同步,所以而變成所謂的:預測拉扯。

  另外一個解決方案,我給它取名叫 驗證同步,聽名字也知道,大體的意思就是每條指令在經(jīng)過服務器驗證通過了以后再執(zhí)行動作。具體的思路如下:首先也需要在每個玩家連接類型里面定義一個TimeModified,然后在客戶端響應玩家鼠標行走的同時,客戶端并不會先行走動,而是發(fā)一條走路的指令給服務器,然后等待服務器的驗證。服務器接受到這條消息以后,進行邏輯層的驗證,然后計算出需要廣播的范圍,包括玩家A在內(nèi),根據(jù)各個客戶端不同的TimeModified生成不同的消息頭,開始廣播,這個時候這個玩家的走路信息就是完全同步的了。這個方法的優(yōu)點是能保證各個客戶端之間絕對的同步,缺點是當網(wǎng)絡延遲比較大的時候,玩家的客戶端的行為會變得比較不流暢,給玩家?guī)砗懿凰母杏X。該種解決方案的原形在國際上被稱為(Hierarchical master-slave synchronization),80年代以后被廣泛應用于網(wǎng)絡的各個領域。

  最后一種解決方案是一種理想化的解決方案,在國際上被稱為Mutual synchronization,是一種對未來網(wǎng)絡的前景的良好預測出來的解決方案。這里之所以要提這個方案,并不是說我們已經(jīng)完全的實現(xiàn)了這種方案,而只是在網(wǎng)絡游戲領域的某些方面應用到這種方案的某些思想。我對該種方案取名為:半服務器同步。大體的設計思路如下:

  首先客戶端需要在登陸世界的時候建立很多張廣播列表,這些列表在客戶端后臺和服務器要進行不及時同步,之所以要建立多張列表,是因為要廣播的類型是不止一種的,比如說有l(wèi)ocal message,有remote message,還有global message 等等,這些列表都需要在客戶端登陸的時候根據(jù)服務器發(fā)過來的消息建立好。在建立列表的同時,還需要獲得每個列表中廣播對象的TimeModified,并且要維護一張完整的用戶狀態(tài)列表在后臺,也是不及時的和服務器進行同步,根據(jù)本地的用戶狀態(tài)表,可以做到一部分決策由客戶端自己來決定,當客戶端發(fā)送這部分決策的時候,則直接將最終決策發(fā)送到各個廣播列表里面的客戶端,并對其時間進行校對,保證每個客戶端在收到的消息的時間是和根據(jù)本地時間進行校對過的。那么再采用預測拉扯中提到過的計算提前量,提高速度行走過去的方法,將會使同步變得非常的smooth。該方案的優(yōu)點是不通過服務器,客戶端自己之間進行同步,大大的降低了由于網(wǎng)絡延遲而帶來的誤差,并且由于大部分決策都可以由客戶端來做,也大大的降低了服務器的資源。由此帶來的弊端就是由于消息和決策權都放在客戶端本地,所以給外掛提供了很大的可乘之機。

  綜合以上三種關于網(wǎng)絡同步派系的優(yōu)缺點,綜合出一套關于網(wǎng)絡游戲傳輸同步的較完整的解決方案,我稱它為綜合同步法(colligate synchronization)。大體設計思路如下:

  首先將服務器需要同步的所有消息從劃分一個優(yōu)先等級,然后按照3/4的比例劃分出重要消息和非重要消息,對于非重要消息,把決策權放在客戶端,在客戶端邏輯上建立相關的決策機構(gòu)和各種消息緩存區(qū),以及相關的消息緩存區(qū)管理機構(gòu).

  對于非重要消息,客戶端的大體處理流程,其中有一個客戶端被動行為值得大家注意,其中包括對服務器發(fā)過來的某些驗證代碼做返回,來確保消息緩存中的消息和服務器端是一致的,從而有效的防止外掛來篡改本地消息緩存。其中的消息來源是包括本地的客戶端響應玩家的消息以及遠程服務器傳遞過來的消息。

  對于重要消息,比如說戰(zhàn)斗或者是某些牽扯到玩家一些比較敏感數(shù)據(jù)的操作,則采用另外一套方案,該方案首先需要在服務器和客戶端之間建立一套Ping System,然后服務器保存和用戶的及時的ping值,當ping比較小的時候,響應玩家消息的同時先不進行動作,而是先把該消息反饋給服務器,并且阻塞,服務器收到該消息,進行邏輯驗證之后向所有該詳細廣播的有效對象進行廣播(包括消息發(fā)起者),然后客戶端收到該消息的驗證,才開始執(zhí)行動作。而當ping比較大的時候,客戶端響應玩家消息的同時立刻進行動作,并且同時把該消息反饋給服務器,值得注意的是這個時候還需要在本地建立一個無驗證消息的隊列,把該消息入隊,執(zhí)行動作的同時等待服務器的驗證,還需要保存當前狀態(tài)。服務器收到客戶端的請求后,進行邏輯驗證,并把消息反饋到各個客戶端,帶上各個客戶端校對過的本地時間。如果驗證通過不過,則通知消息發(fā)起者,該消息驗證失敗,然后客戶端自動把已經(jīng)在進行中的動作取消,恢復原來狀態(tài)。如果驗證通過,則廣播到的各個客戶端根據(jù)從服務器獲得校對時間進行對其進行拉扯,保證在該行為完成之前完成同步。

 

  至此,一個比較成熟的網(wǎng)絡游戲的同步機制已經(jīng)初步建立起來了,接下來的邏輯代碼就根據(jù)各自不同的游戲風格以及側(cè)重點來寫了。

  同步是網(wǎng)絡游戲最重要的問題,如何同步也牽扯到各個方面的問題,比如說游戲的規(guī)模,游戲的類型以及各種各樣的方面,對于規(guī)模比較大的游戲,在同步方面可以下很多的工夫,把消息分得十分的細膩,對于不同的消息采用不同的同步機制,而對于規(guī)模比較小的游戲,則可以采用大體上一樣的同步機制,究竟怎么樣同步,沒有個定式,是需要根據(jù)自己的不同情況來做出不同的同步?jīng)Q策的



網(wǎng)游同步算法之導航推測(Dead Reckoning)算法:


  在了解該算法前,我們先來談談該算法的一些背景資料。大家都知道,在網(wǎng)絡傳輸?shù)臅r候,延遲現(xiàn)象是很普遍的,而在基于Server/Client結(jié)構(gòu)下的網(wǎng)絡游戲的同步也就成了很頭疼的問題,在保證客戶端響應用戶本地指令流暢的情況下,沒法有效的保證的同步的及時性。同樣,在軍方也有類似的事情發(fā)生,即使是同一LAN里面的機器,也會因為傳輸?shù)难舆t,導致一些運算的失誤,介于此,美國國防部投入了大量的資金用于研究一種比較的好的方案來解決分布式系統(tǒng)中的延遲問題,特別是一個叫分布式模擬運動(Distributed Interactive Simulation)的系統(tǒng),這套系統(tǒng)呢,其中就提出了一套號稱是Latency Hiding & Bandwidth Reduction的方案,命名為Dead Reckoning。呵呵,來頭很大吧,恩,那么我們下面就來看看這套系統(tǒng)的一些觀點,以及我們?nèi)绾伟阉\用到我們的網(wǎng)絡游戲的同步中。

posted @ 2010-07-08 15:57 鄭興鋒 閱讀(966) | 評論 (0)編輯 收藏

  在Windows網(wǎng)絡編程中,一般我們要用到的網(wǎng)絡模型就5種, 分別是, select模型,WSAAsyncSelect模型,WSAEventSelect模型,重疊模型, 完成端口模型。
  這幾種模型都可以用在網(wǎng)絡開發(fā)中,但是根據(jù)不同的項目和不同的環(huán)境,有不同的選擇,如果服務器端的連接數(shù)不是很多時,假如100以內(nèi),這幾種模型都可以用,完成端口模型在連接數(shù)不多時顯的有點復雜了, select模型,WSAAsyncSelect模型,WSAEventSelect模型更適合用在客戶端連接數(shù)不多的情況。
  WSAAsyncSelect模型更適合用在有窗口的客戶端程序中,因為它是這幾個模型中,唯一和窗口句柄和窗口過程關聯(lián)的模型,如果沒有窗口的客戶端程序中, select模型,WSAEventSelect模型都可以用, select模型更簡單一些。
  最后我們來談談完成端口模型, 完成端口模型是比較復雜的,它適合用在上千個客戶連接的服務器開發(fā),我覺的它和前面幾個模型最大不同之處在與,它是在每次網(wǎng)絡事件觸發(fā)前,將函數(shù)注冊,而其他的模型是事件觸發(fā)時調(diào)用相應的網(wǎng)絡事件函數(shù)(呵呵,不知道Windows內(nèi)核為什么要這么做)。

posted @ 2010-06-22 15:15 鄭興鋒 閱讀(559) | 評論 (0)編輯 收藏

本文討論的前提是在C++標準下的類和結(jié)構(gòu)體,而不是討論C中的結(jié)構(gòu)體.
在C++中,類和結(jié)構(gòu)體的唯一區(qū)別是成員的可見性(兩者都支持數(shù)據(jù)和成員函數(shù)以及構(gòu)造函數(shù)和析構(gòu)函數(shù)).
對于類來說,成員默認為私有.
對于結(jié)構(gòu)體來說,成員默認為公有.
對于繼承來說,類之間的繼承,成員默認為私有,而結(jié)構(gòu)體之間的繼承則默認為公有.

如果是類和結(jié)構(gòu)體之間的繼承,情況會怎樣呢?

class A
{
public:
int a;
};

struct B : A { };

struct C
{
int c;
};

class D : C
{
};

int main()
{
B b;
D d;
b.a = 1;
d.c = 2;
}

用 C++編譯器編譯上面的代碼,會在 d.c = 2;處報錯,VC 6.0給出的錯誤提示:error C2248: ‘c’ : cannot access public member declared in class ‘C’,看起來有點匪夷所思啊,不能訪問公有成員(既然都公有了,還不能訪問?).
相應的C++標準 11.2.2 of ISO/IEC 14882-2003文檔:
the kind of inheritance is determined by the derived class being declared as a class or struct when an access specificer for the base class is absent.
當被繼承的基類缺少存取說明符的修飾時, 繼承的類型由被聲明為類或者結(jié)構(gòu)體的派生類所決定.
示例中class D : C, 基類C并沒有存取說明符的修飾,那么集成的類型就由派生類D來決定,D被聲明為類(而非結(jié)構(gòu)體),對于類來說,類之間的繼承,成員默認為私有,所以實際上此時的int c;應該為私有,那么上面的編譯錯誤也就可以解釋通了.
我們可以試著把class D : C 改為 class D : public C,就可以編譯通過了.

posted @ 2010-06-09 12:21 鄭興鋒 閱讀(842) | 評論 (0)編輯 收藏

本文使用的表示方法和VC6的Memory視圖一致,即:左上表示低位。

 

提示2:下文提到的“類大小”嚴格上來說是該類經(jīng)過實例化的對象的大小。當然了,光研究長度的話,兩者差別不大,因為:CClassA objA,sizeof(CClassA)和sizeof(objA)得到的結(jié)果都是一樣的。

 

一、真空類

class CNull

{

};

長度:1

內(nèi)存結(jié)構(gòu):

??

評注:長度其實為0,這個字節(jié)作為內(nèi)容沒有意義,可能每次都不一樣。

 

二、空類

class CNull2

{

public:

    CNull2(){printf("Construct\n");}

    ~CNull2(){printf("Desctruct\n");}

    void Foo(){printf("Foo\n");}

};

長度:1

內(nèi)存結(jié)構(gòu):

??

評注:同真空類差不多,內(nèi)部的成員函數(shù)并不會影響類大小。

 

三、簡單類

class COneMember

{

public:

    COneMember(int iValue = 0){m_iOne = iValue;};

private:

    int m_iOne;

};

長度:4

內(nèi)存結(jié)構(gòu):

00 00 00 00 //m_iOne

評注:成員數(shù)據(jù)才影響類大小。

 

四、簡單繼承

class CTwoMember:public COneMember

{

private:

    int m_iTwo;

};

長度:8

內(nèi)存結(jié)構(gòu):

00 00 00 00 //m_iOne

CC CC CC CC //m_iTwo

評注:子類成員接在父類成員之后。

 

五、再繼承

class CThreemember:public CTwoMember

{

public:

    CThreemember(int iValue=10) {m_iThree = iValue;};

private:

    int m_iThree;

};

長度:12

內(nèi)存結(jié)構(gòu):

00 00 00 00 //m_iOne

CC CC CC CC //m_iTwo

0A 00 00 00 //m_iThree

評注:孫類成員接在子類之后,再再繼承就依此類推了。

 

六、多重繼承

class ClassA

{

public:

    ClassA(int iValue=1){m_iA = iValue;};

private:

    int m_iA;

};

 

class ClassB

{

public:

    ClassB(int iValue=2){m_iB = iValue;};

private:

    int m_iB;

};

 

class ClassC

{

public:

    ClassC(int iValue=3){m_iC = iValue;};

private:

    int m_iC;

};

 

class CComplex :public ClassA, public ClassB, public ClassC

{

public:

    CComplex(int iValue=4){m_iComplex = iValue;};

private:

    int m_iComplex;

};


長度:16

內(nèi)存結(jié)構(gòu):

01 00 00 00 //A

02 00 00 00 //B

03 00 00 00 //C

04 00 00 00 //Complex

評注:也是父類成員先出現(xiàn)在前邊,我想這都足夠好理解。

 

七、復雜一些的繼承

不寫代碼了,怕讀者看了眼花,改畫圖。

長度:32

內(nèi)存結(jié)構(gòu):

01 00 00 00 //A

02 00 00 00 //B

03 00 00 00 //C

04 00 00 00 //Complex

00 00 00 00 //OneMember

CC CC CC CC //TwoMember

0A 00 00 00 //ThreeMember

05 00 00 00 //VeryComplex

評注:還是把自己的成員放在最后。

 

只要沒涉及到“虛”(Virtual),我想沒什么難點,不巧的是“虛”正是我們要研究的內(nèi)容。

 

八、趁熱打鐵,看“虛繼承”

class CTwoMember:virtual public COneMember

{

private:

    int m_iTwo;

};

長度:12

內(nèi)存結(jié)構(gòu):

E8 2F 42 00 //指針,指向一個關于偏移量的數(shù)組,且稱之虛基類偏移量表指針

CC CC CC CC // m_iTwo

00 00 00 00 // m_iOne(虛基類數(shù)據(jù)成員)

評注:virtual讓長度增加了4,其實是多了一個指針,關于這個指針,確實有些復雜,別的文章有具體分析,這里就不岔開具體講了,可認為它指向一個關于虛基類偏移量的數(shù)組,偏移量是關于虛基類數(shù)據(jù)成員的偏移量。

 

九、“閉合”虛繼承,看看效果

長度:24

內(nèi)存結(jié)構(gòu):

14 30 42 00 //ClassB的虛基類偏移量表指針

02 00 00 00 //m_iB

C4 2F 42 00 //ClassC的虛基類偏移量表指針

03 00 00 00 //m_iC

04 00 00 00 //m_iComplex

01 00 00 00 //m_iA

評注:和預料中的一樣,虛基類的成員m_iA只出現(xiàn)了一次,而且是在最后邊。當然了,更復雜的情況要比這個難分析得多,但虛繼承不是我們研究的重點,我們只需要知道:虛繼承利用一個“虛基類偏移量表指針”來使得虛基類即使被重復繼承也只會出現(xiàn)一次。

 

十、看一下關于static成員

class CStaticNull

{

public:

    CStaticNull(){printf("Construct\n");}

    ~CStaticNull(){printf("Desctruct\n");}

    static void Foo(){printf("Foo\n");}

    static int m_iValue;

};

長度:1

內(nèi)存結(jié)構(gòu):(同CNull2)

評注:可見static成員不會占用類的大小,static成員的存在區(qū)域為靜態(tài)區(qū),可認為它們是“全局”的,只是不提供全局的訪問而已,這跟C的static其實沒什么區(qū)別。

 

十一、帶一個虛函數(shù)的空類

class CVirtualNull

{

public:

    CVirtualNull(){printf("Construct\n");}

    ~CVirtualNull(){printf("Desctruct\n");}

    virtual void Foo(){printf("Foo\n");}

};

長度:4

內(nèi)存結(jié)構(gòu):

00 31 42 00 //指向虛函數(shù)表的指針(虛函數(shù)表后面簡稱“虛表”)

 

00423100:(虛表)

41 10 40 00 //指向虛函數(shù)Foo的指針

 

00401041:

E9 78 02 00 00 E9 C3 03 … //函數(shù)Foo的內(nèi)容(看不懂)

評注:帶虛函數(shù)的類長度就增加了4,這個4其實就是個指針,指向虛函數(shù)表的指針,上面這個例子中虛表只有一個函數(shù)指針,值就是“0x00401041”,指向的這個地址就是函數(shù)的入口了。

 

十二、繼承帶虛函數(shù)的類

class CVirtualDerived : public CVirtualNull

{

public:

    CVirtualDerived(){m_iVD=0xFF;};

    ~CVirtualDerived(){};

private:

    int m_iVD;

};

長度:8

內(nèi)存結(jié)構(gòu):

3C 50 42 00 //虛表指針

FF 00 00 00 //m_iVD

 

0042503C:(虛表)

23 10 40 00 //指向虛函數(shù)Foo的指針,如果這時候創(chuàng)建一個CVirtualNull對象,會發(fā)現(xiàn)它的虛表的內(nèi)容跟這個一樣

評注:由于父類帶了虛函數(shù),子類就算沒有顯式聲明虛函數(shù),虛表還是存在的,虛表存放的位置跟父類不同,但內(nèi)容是同的,也就是對父類虛表的復制。

 

十三、子類有新的虛函數(shù)

class CVirtualDerived: public CVirtualNull

{

public:

    CVirtualDerived(){m_iVD=0xFF;};

    ~CVirtualDerived(){};

    virtual void Foo2(){printf("Foo2\n");};

private:

    int m_iVD;

};

長度:8

內(nèi)存結(jié)構(gòu):

24 61 42 00 //虛表指針

FF 00 00 00 //m_iVD

 

00426124:(虛表)

23 10 40 00

50 10 40 00

評注:虛表還是只有一張,不會因為增加了新的虛函數(shù)而多出另一張來,新的虛函數(shù)的指針將添加在復制了的虛表的后面。

 

十四、當純虛函數(shù)(pure function)出現(xiàn)時

class CPureVirtual

{

    virtual void Foo() = 0;

};

 

class CDerivePV : public CPureVirtual

{

    void Foo(){printf("vd: Foo\n");};

};

長度:4(CPureVirtual),4(CDerivePV)

內(nèi)存結(jié)構(gòu):

CPureVirtual:

(不可實例化)

 

CDerivePV:

28 50 42 00 //虛表指針

 

00425028:(虛表)

5A 10 40 00 //指向Foo的函數(shù)指針

評注:帶純虛函數(shù)的類不可實例化,因此列不出其“內(nèi)存結(jié)構(gòu)”,由其派生類實現(xiàn)純虛函數(shù)。我們可以看到CDerivePV雖然沒有virtual聲明,但由于其父類帶virtual,所以還是繼承了虛表,如果CDerivePV有子類,還是這個道理。

 

十五、虛函數(shù)類的多重繼承

前面提到:(子類的虛表)不會因為增加了新的虛函數(shù)而多出另一張來,但如果有多重繼承的話情況就不是這樣了。下例中你將看到兩張?zhí)摫怼?/p>

大小:24

內(nèi)存結(jié)構(gòu)

F8 50 42 00 //虛表指針

01 00 00 00 //m_iA

02 00 00 00 //m_iB

E8 50 42 00 //虛表指針

03 00 00 00 //m_iC

04 00 00 00 //m_iComplex

 

004250F8:(虛表)

5A 10 40 00 //FooA

55 10 40 00 //FooB

64 10 40 00 //FooComplex

 

004250E8:(虛表)

5F 10 40 00 //FooC

評注:子類的虛函數(shù)接在第一個基類的虛函數(shù)表的后面,所以B接在A后面,Complex接在B后面。基類依次出現(xiàn),子類成員接在最后面,所以m_iComplex位于最后面。

posted @ 2010-06-08 16:01 鄭興鋒 閱讀(383) | 評論 (0)編輯 收藏

最近編程過程中遇到的一個BUG.

 首先我來描述一下,這個BUG是CString類的使用引起的,在編程過程中有個默認的規(guī)則,就是CStirng, std::string這種變長的數(shù)據(jù)類型是不可以做為模塊參數(shù)進行傳遞和調(diào)用, 因為會引起崩潰, 這種情況我
也遇到過,但是這個錯誤并不是因為做為模塊參數(shù)而引起的,而是因為包含Cstring 的結(jié)構(gòu)體,在類定義時,

成員變量的順序引起的,也就說將包含CSting類的結(jié)構(gòu)體放在某個變量(這個變量是一個指針連表)前時,會出錯,而放變量的后面就不出錯,原因是因為包含CString類的結(jié)構(gòu)體在一個線程中進行了修改,因為CString類是變長的,所以寫入了大量的數(shù)據(jù)。使得CString類的地址覆蓋了,它前面變量的地址,所以在程序退出時,刪除錯誤的指針地址,造成崩潰。

posted @ 2010-06-08 13:35 鄭興鋒 閱讀(530) | 評論 (4)編輯 收藏

     最近在學習服務架構(gòu)和服務器編程,隨著學習的進展,給我?guī)砹艘恍﹩栴},其中QQ服務器是如何實現(xiàn)的讓我困惑了一段時間,最近略有感悟,寫下來分享一下,以方便大家的交流和學習。

  因為以前做過游戲開發(fā)對游戲服務器的架構(gòu)和實現(xiàn)有一定的了解,一組游戲服務器如果能承受2000人同時在線已經(jīng)算不錯了,而且每組服務器和每組服務器是獨立的,就是說每個玩家只能和本服務器的玩家進行交流和互動,和其他服務不實現(xiàn)通信,然而QQ好象能做到只要安裝客戶端的用戶,可以查找到任何QQ用戶并進行聊天,發(fā)送文件,音頻,視頻等。

 經(jīng)過一些資料的查找和分析,了解的QQ是有p2p通信來實現(xiàn)的,這樣不經(jīng)過服務器的中轉(zhuǎn),減輕了服務器的負擔,其中有一鍛文章是這么寫的,我抄出其中的一部分,其他的在打開這個連接就能看到全文(http://bbs.51cto.com/thread-591907-1.html):
   “A要向B發(fā)送一個文件,于是發(fā)出一個文件傳送請求。服務器收到這個文件傳送請求后,轉(zhuǎn)發(fā)給B,同時或者在B應答后,將A的IP地址同時發(fā)送給B。B這個時候就得到了A的真實IP。這里的IP是你的本機IP。也就是說,如果A處在內(nèi)網(wǎng),B得到的地址就是一個內(nèi)網(wǎng)地址。B得到了A的地址之后,就會嘗試去連接A。如果B也處于內(nèi)網(wǎng),那么,顯然A跟B之間的連接是無法建立的。這個時候,客戶端就會請求服務器進行文件中轉(zhuǎn)。因為服務器具有公網(wǎng) IP,處在內(nèi)網(wǎng)的A跟B都是可以連接到服務器的,于是,A跟B的文件傳送就通過服務器中轉(zhuǎn)的方式,順利進行”

   在這篇文章中寫到,“客戶端就會請求服務器進行文件中轉(zhuǎn)。因為服務器具有公網(wǎng) IP,處在內(nèi)網(wǎng)的A跟B都是可以連接到服務器的,于是,A跟B的文件傳送就通過服務器中轉(zhuǎn)的方式,順利進行”如果是這樣的話,那么我們就有一個前提,即A和B連接在同一臺服務器上,如果A和B不在同一臺服務怎么辦呢。估計只能用UDP通信了,能進行UDP通信,進行打洞就可以了,為什么還要服務器中轉(zhuǎn)。

 所以我認為應該是這樣的,假設A,B是兩個客戶端, C, D是兩臺服務器,為了避免混淆,后面就用A客,B客, C服, D服來代表,A客---連接---C服, B客---連接---D服, A和C之間是用TCP建立的連接,B和D之間也是有TCP建立的連接,A和B是在不同的內(nèi)網(wǎng)上,如果A和B之間要建立ptp連接如何建立?那么A和B之間必須進行NAT打洞,這就要求C服和B客通信,D服和A客通信, 如果C服要給B發(fā)信息,因為C和B之間沒有TCP面向連接的通信,所以他們只能用UDP通信, 因為C和D是有公網(wǎng)ip的,所以C和B的通過UDP是肯定可以通信,這樣A告訴C它要連接B,C通過數(shù)據(jù)庫找的B的地址,和B通信,告訴B A的地址,同樣A用同樣的方式也可以獲得B的地址,這樣即可以實現(xiàn)A和B的打洞,又能實現(xiàn)上線通知,而且和連接那臺服務器沒關系,每次有新用戶登陸是,進行負載均衡,和比較空閑的服務器連接就可以了,每組服務器配置相同,只需要增加服務器就能滿足不斷增長的用戶需求。

posted @ 2010-06-07 15:05 鄭興鋒 閱讀(7353) | 評論 (4)編輯 收藏

僅列出標題
共2頁: 1 2 
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲精品1234| 欧美亚洲综合在线| 国产精品乱码妇女bbbb| 久久综合亚州| 国产精品视频观看| 欧美α欧美αv大片| 欧美视频在线一区| 亚洲激精日韩激精欧美精品| 欧美片网站免费| 一区二区高清视频| 久久综合999| 欧美激情片在线观看| 亚洲高清免费视频| 久久免费一区| 欧美日韩国产va另类| 中日韩高清电影网| 欧美另类一区二区三区| 美女亚洲精品| 黑人中文字幕一区二区三区| 亚洲国产一区二区三区在线播| 亚洲免费观看高清在线观看 | 久久精品男女| 黑人中文字幕一区二区三区| 亚洲欧洲三级电影| 亚洲女女女同性video| 国产精品国产三级欧美二区| 国产精品99久久久久久www| 亚洲欧洲精品一区二区三区| 亚洲欧美另类综合偷拍| 亚洲一级在线观看| 欧美精品日韩一区| 亚洲激情婷婷| 亚洲影视在线| 在线 亚洲欧美在线综合一区| 欧美精品福利视频| 免费久久精品视频| 久久激情中文| 9i看片成人免费高清| 国产精品激情电影| 欧美视频导航| 欧美日韩一区二区三区在线看| 午夜一区不卡| 欧美一区二区三区日韩| 亚洲免费在线观看| 亚洲视频在线一区| 亚洲一区亚洲| 国产精品三级视频| 欧美xx69| 欧美日韩国产欧| 国产美女搞久久| 国产精品乱码妇女bbbb| 国产精品稀缺呦系列在线| 欧美电影电视剧在线观看| 麻豆av福利av久久av| 欧美成人一区二区三区在线观看| 免费亚洲电影| 日韩网站在线观看| 欧美在线观看日本一区| 欧美成人精品h版在线观看| 欧美激情精品久久久久久免费印度| 久久在线免费视频| 亚洲国产精品女人久久久| 亚洲理伦在线| 久久国产精品毛片| 欧美日韩精品三区| 国产一区二区三区不卡在线观看| 一区二区三区日韩欧美精品| 久久精品一区| 日韩一级精品视频在线观看| 欧美一区二区三区免费视| 男人天堂欧美日韩| 99视频在线观看一区三区| 亚洲精品网址在线观看| 亚洲日本va在线观看| 99精品国产热久久91蜜凸| 日韩视频永久免费| 亚洲自拍三区| 久久久精品国产免大香伊| 欧美成人蜜桃| 久久综合久久久久88| 国产精品影片在线观看| 亚洲女性裸体视频| 国产精品国产三级国产a| 亚洲视频在线观看| 国产精品激情电影| 欧美在线黄色| 亚洲成色最大综合在线| 亚洲精品视频在线观看网站| 欧美日韩视频第一区| 亚洲一区二区欧美日韩| 久久视频免费观看| 亚洲精品一区在线观看| 国产精品福利在线观看网址| 国产女同一区二区| 欧美一区二区三区在线播放| 99精品欧美一区二区蜜桃免费| 亚洲黄色一区| av成人毛片| 久久久无码精品亚洲日韩按摩| 亚洲品质自拍| 国产亚洲人成a一在线v站| 亚洲女人天堂av| 久久国产88| 亚洲国产欧美日韩精品| 欧美激情影院| 久久漫画官网| 久久香蕉精品| 亚洲素人一区二区| 久久免费精品视频| 欧美视频二区| 亚洲精品欧美日韩专区| 久久不见久久见免费视频1| 亚洲精品国产精品国自产在线| 欧美在线视频观看免费网站| 欧美日韩国产综合一区二区| 久久精品午夜| 国产一区二区久久精品| 亚洲四色影视在线观看| 日韩一二三区视频| 欧美国产日本高清在线| 亚洲人成在线播放| 亚洲三级毛片| 国产精品卡一卡二卡三| 欧美日韩日本网| 久久一区免费| 噜噜噜91成人网| 精品999网站| 久久精品国产精品亚洲综合 | 亚洲中字在线| 久久精品一区二区三区四区| 牛人盗摄一区二区三区视频| 午夜一区二区三区在线观看| 日韩一区二区精品| 91久久综合亚洲鲁鲁五月天| 精品成人一区| 国产主播在线一区| 国产精品免费一区二区三区观看| 欧美日韩裸体免费视频| 欧美精品日本| 欧美激情第一页xxx| 欧美h视频在线| 免费观看成人| 欧美成人免费va影院高清| 快she精品国产999| 麻豆精品视频在线| 老司机午夜精品| 久久亚洲春色中文字幕久久久| 欧美在线免费一级片| 欧美一区二区三区男人的天堂| 欧美在线观看网站| 久久久久一区二区| 蜜桃av一区二区| 欧美激情欧美激情在线五月| 欧美国产日韩精品免费观看| 亚洲第一二三四五区| 欧美国产日韩在线观看| 欧美大片在线看| 欧美激情亚洲| 欧美色欧美亚洲另类二区| 久久久久久穴| 免费在线亚洲| 亚洲国产一区在线观看| 亚洲人成人一区二区在线观看| 久热综合在线亚洲精品| 亚洲视频免费| 亚洲一区尤物| 久久精品一区二区三区四区 | 欧美大尺度在线观看| 欧美成人综合在线| 亚洲国产高清一区| 性欧美videos另类喷潮| 国产精品99久久不卡二区| 国产精品网曝门| 亚洲一级一区| 久久精品99| 亚洲一区二区三区高清 | 亚洲日韩欧美一区二区在线| 一区二区精品在线| 亚洲欧洲综合另类| 亚洲欧美卡通另类91av| 国产精品私房写真福利视频| 欧美电影美腿模特1979在线看| 一本色道久久综合亚洲91| 久久九九全国免费精品观看| 一本色道88久久加勒比精品| 久久久欧美精品sm网站| 国产视频精品xxxx| 久久久精品2019中文字幕神马| 久久综合久久久久88| 亚洲一区二区三区久久| 国产日韩精品一区二区三区在线| 欧美日韩精品一区二区| 欧美午夜不卡| 国产精品国产精品| 国产精品伦子伦免费视频| 久久久久亚洲综合| 国产精品天天摸av网| 国产精品国产三级国产aⅴ9色| 久久国产一区| 欧美亚洲一级|