宣告

本人萌新一枚,以後想進入遊戲開發行業,so,開始自學《網路遊戲伺服器端程式設計》一書,在部落格上寫筆記以記錄提取一些書中我自認為有用的知識點,如有侵權或者一些別的問題,請私信我,謝謝!

網路程式設計基礎

網路遊戲伺服器端開發概述

Client/Server(客戶端/伺服器端)是現在網路遊戲的最基本的框架,而從開發的角度看,又分為一下三種類型:

  1. 對等的客戶端與伺服器端 嚴格地說,對等的客戶端和伺服器端並不是人們經常意義上所說的網路遊戲,而是諸如魔獸爭霸、星際爭霸、CS……這些比較流行的網路對戰遊戲。這類遊戲的特點就是:支援區域網對戰,在建立對局時,開設對局房間的電腦將作為主機——伺服器,其他與之相連的電腦作為客戶端;每局完成之後,可以隨意更換電腦作為伺服器。 這類網路遊戲的主要特點如下: (1)遊戲週期相對較短,以一局遊戲為一個週期,完成一局後,玩家可以選擇退出遊戲,重新開始新的遊戲。可以保留剛才的伺服器,也可以另外選擇伺服器。 (2)遊戲的所有核心邏輯演算法獨立地在每個玩家的客戶端上執行,不依賴於伺服器而存在,其設計理念與單機遊戲相仿。玩家的行為被髮送到其他玩家的客戶端,用來進行玩家間的互動。因此,遊戲玩家的資料沒有辦法儲存,這種網路遊戲的結構只適用於對戰型別的網路遊戲。 (3)這種遊戲通常基於區域網,範圍較小。
  2. 基於大廳的網路遊戲 網路遊戲大廳,現在廣為人知的QQ遊戲大廳,就是這種型別的遊戲。大廳就是一箇中介,是一臺專門的伺服器,它的作用並不是作為遊戲的主機存在,而是為不同位置的玩家牽線搭橋,提供機會讓不同區域的玩家能有在一起遊戲。特點: (1)大廳只負責吧不同的客戶端撮合到一起。各個客戶端可以自行開始遊戲。在進行遊戲是,玩家只和自己加入的伺服器發生互動,遊戲結束後,由主機向大廳彙報遊戲結果。 (2)在於大廳相連的遊戲資料庫中,存放有玩家的賬戶資訊以及積分資訊,玩家的遊戲分數可以得到儲存。 (3)作為遊戲大廳的伺服器同樣不包含核心邏輯運算,它更像是獨立於遊戲之外的一個輔助軟體,作用只是提供多個遊戲伺服器房間的連線供玩家選擇,讓玩家可以通過相互得分進行比較。在每個遊戲房間裡的玩家則是地位平等的,每個玩家既可以充當伺服器,也可以充當客戶端。
  3. 純C/S結構的網路遊戲 我們所說的MMORPG(多人線上網路角色扮演遊戲),是純C/S結構的網路遊戲。這類遊戲有一到多個伺服器,成千上萬的玩家同時線上,玩家在遊戲世界裡持續存在,並且玩家的資訊被儲存下來。在這種結構裡,為了保證所有的客戶端都具有相同的遊戲畫面和遊戲結果,關鍵的數值計算和邏輯判斷必須放在伺服器端,因此伺服器端必須具備完整的遊戲世界模型。客戶端相當於一個視窗,玩家通過這個視窗來觀察遊戲世界並在其中進行互動。現在較為火爆的網路遊戲,如夢幻西遊、魔獸世界、劍網三等都是這樣的結構。 這類網路遊戲的特點如下: (1)嚴格的區分伺服器端和客戶端,兩者的開發及執行分開進行,玩家只能接觸到客戶端,伺服器端的維護由運營商來完成。 (2)這類遊戲的核心邏輯都放在伺服器端,包括玩家的賬戶資訊、玩家的角色資訊、怪物的血量傷害計算、怪物重新整理等,客戶端只負責顯示畫面和一些非核心的運算,所以,這類遊戲要求玩家必須保持與伺服器的連線。 (3)遊戲世界具備良好的持續性,網路遊戲運營商負責伺服器端的維護,整個遊戲世界的架構都是放在伺服器端,可以不斷地進行擴充。

網路通訊協議

  1. 網路協議 計算機在網上交換資訊,都需要在不同的系統的實體之間進行通訊,兩個實體(實體間對等的應用程式等)要成功的交換資訊,就必須遵守相互間能夠接受的規則。這些規則的集合被稱為協議(protocol),它可以定義為兩個實體間控制資料交換的規則的集合。 最常提到的網路協議就是TCP/IP(Transmission Control Protocol/Internet Protocol),事實上,TCP/IP是一個協議的結合(成為協議族),而另一些系統則可能使用IPX(InterPacket Exchange)協議。
  2. TCP/IP協議 TCP/IP對應於一個4層的概念模型,稱為DARPA模型,這4層從上到下依次是: 應用層(Application) 傳輸層(Transport) 網路層(Network) 網路訪問層(Network Access) 1.應用層 應用層對應於OSI模型的應用層,給應用程式提供訪問其他層服務的能力並定義應用程式用於交換資料的協議。 2.傳輸層 傳輸層對應於OSI模型的傳輸層和部分會話層功能。它負責給應用層提供會話和資料報通訊服務。傳輸層的核心協議是傳輸控制協議(Transmission Control Protocol,TCP)和使用者資料報協議(User Datagram Protocol,UDP) 3.網路層 網路層也稱網際網路層,它對應於OSI模型的網路層,負責定址、打包以及從一臺計算機通過一個或多個路由器到最終目標的包轉發機制。 4.網路訪問層 網路訪問層對應於OSI模型的物理層和資料鏈路層,並負責把TCP/IP包放到網路傳輸介質和從網路傳輸介質上接收TCP/IP包。
  3. TCP/IP協議族 1.IP 網間協議(Internet Protocol),負責主機間資料的路由和網路上資料的儲存,同時為ICMP、TCP、UDP提供分組傳送服務。使用者程序通常不涉及這一層。 2.ARP 地址解析協議(Address Resolution Protocol),此協議將網路地址對映到硬體地址。 3.RARP 反向地址解析協議(Reverse Address Resolution Protocol),此協議將硬體地址對映到網路地址。 4.ICMP 網際控制報文協議(Internet Control Message Protocol),此協議處理資訊和主機的差錯和傳送控制。 5.TCP 傳送控制協議(Transmission Control Protocol),這是一種提供給使用者程序的可靠的面向連線的全雙工位元組流協議。 它要為使用者程序提供虛擬電路服務,併為資料可靠傳輸建立檢查。大多數網路使用者程式視同TCP。 6.UDP 使用者資料報協議(User Datagram Protocol),這是提供給使用者程序的無連線協議。用於傳輸資料而不執行正確性檢查。 7.FTP 檔案傳輸協議(File Transfer Protocol),允許使用者以檔案操作的方式(檔案的增、刪、改、查、傳送等)與另一主機相互通訊。 8.SMTP 簡易郵件傳送協議(Simple Mail Transfer Protocol),SMTP協議為系統之間傳送電子郵件。 9.TTP 終端協議(Telnet Terminal Protocol),允許使用者以虛擬終端方式訪問遠端主機。 10.HTTP 超文字傳輸協議(Hypertext Transfer Protocol)。用於傳輸超文字標記語言寫的檔案,也就是人們常說的網頁。 11.TFTP 簡易檔案傳輸協議(Trivial File Transfer Protocol)。用於傳送“簡單”的檔案,與FTP不同的是,它使用的是UDP的69埠,因此它可以穿越許多防火牆。

Socket程式設計原理

網路遊戲的傳輸層採用的是Socket介面來實現,這樣避免了開發人員直接面對複雜的網路協議,又具有一定的靈活性,可以在Socket底層上構架自己的傳輸協議。同時也可以實現跨協議的開發。

  1. 套接字(Socket) 套接字(Socket)=網路地址(IP)+埠號(port) Socket有兩種:一種是標準Socket,又稱為Berkeley Socket,主要用於Linux/UNIX系統下開發; 另一種是Winsock,是微軟在標準Socket的基礎上新增了一些針對Windows的擴充套件函式,主要用於在Windows平臺下開發。
  2. Socket通訊流程 Socket介面位於網路通訊協議和應用程式之間,使用Socket通訊與打電話相似,都要建立連線。打電話是靠電話號碼繫結,而網路通訊協議則依賴IP地址標誌主機,埠號標誌程序,IP加上埠號才能最終確定連線目標。連線建立後就可以進行雙向的通訊;最後,通訊結束後需要關閉連線。 一個網路連線需要以下5種資訊: 1.本地協議埠:指出接收報文或資料的程序 2.本地主機地址:指出接收資料包的主機 3.遠端協議埠:指出目的程序或程式 4.遠端主機地址:指出目的主機 5.協議:指出程式在網路上傳輸資料時使用的協議 Socket的資料結構包含這五種資訊,也就是說Socket是網路通訊中一個端點的抽象,Socket資料結構包含端點的需要的所有資料元素。Socket結構大大簡化了網路通訊。
  3. Socket函式 以Winsock為例,有一系列的Socket函式,可以使用這些函式來實現Socket通訊。 (1)Socket Socket函式用於建立一個Socket套接字,函式原型如下:
SOCKET socket(
	int af,				//使用的協議族
	//Socket協議族在計算機中表示為一個整數,可以取值為AF_INET.
	int type,			//Socket型別
	//Socket型別有兩種:SOCK_STREAM—代表流Socket
	//					SOCK_DGRAM—代表資料報Socket
	int protocol		//使用的協議地址
);

函式如果成功,返回一個Socket描述字,否則,返回INVALID_SOCKET。 在建立Socket連線之前,必須首先建立所需的Socket連線字

	SOCKET s;
	s = socket(AF_INET, SOCK_STREAM, 0);

(2)Connect Connet函式用於嘗試與遠端建立一個Socket連線。

int connet(
	SOCKET s,							//Socket描述字
	const struct sockaddr* name,		//遠端的地址
	int namelen							//遠端地址的長度
);

在進行連線時,遠端的地址是一個SOCKADDR的結構,其定義為:

struct sockaddr_in{
	short sin_family;				//Socket 族
	u_short sin_port;				//埠
	struct in_addr sin_addr;		//IP地址
	char sin_zero[8];				//結構的長度
};

函式如果連線成功,返回0,否則返回SOCKET_ERROR。 對於非阻塞模式的Socket連線,返回結果通常都是SOCKET_ERROR,並且錯誤程式碼為 WSAEWOULDBLOCK,表示連線正在進行,而不是一個真正的錯誤。 建立連線通常是由客戶端發出連線請求:

	SOCKET s;
	SOCKADDR_IN ServerAddr;
	ServerAddr.sin_family = AF_INET;
	ServerAddr.sin_port = htons(Port);
	ServerAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	connect(s, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr));

(3)Send Send函式用於在某個Socket上向遠端傳送資料,函式原型為:

int send(
	SOCKET s,		//Socket套接字
	const char* buf,//存放傳送資料的緩衝區
	int len,//將要傳送的資料長度
	int flags//傳送時使用的附加引數
);

如果傳送成功,返回值為成功傳送的位元組數,否則返回SOCKET_ERROR。

未完待續……