2012-02-27 65 views
4

過去幾天我一直在使用TCP/IP通信(使用Java和C#)搞了很多。我瞭解它是如何工作的並且能夠使用它。我的問題更多的是一個代碼設計問題,它是如何完成一個真正的溝通的最佳和簡單的方法。網絡通信TCP [代碼設計]

例如我構建了我自己的多用戶聊天服務器。我希望我的通信能夠決定採用Auth請求還是新聊天消息能夠獲取當前用戶列表等。

我自己實現了幾種方式,但我不太滿意因爲我認爲這是一種更加標準和美觀的方式。

我首先想到的是用分隔符至極一個字符串被分裂,這是我在Java中我的通信實現的例子:

//The Object-types im Using 
clientSocket = new Socket(host, port_number); 
_toServer = new PrintStream(clientSocket.getOutputStream()); 
_fromServer = new DataInputStream(clientSocket.getInputStream()); 

//Example Commands my Client sends to the server 

_toServer.println("STATUS|"); //Gets the Status if server is online or closed (closed can occur when server runs but chat is disabled) 
_toServer.println("AUTH|user|pw"); //Sends an auth Request to Server with username and Password 
_toServer.println("MESSAGE|Hello World|ALL"); //Sends hello World in the Normal Chat to all Users 
_toServer.println("MESSAGE|Hello World|PRIVATE|foo"); //Sends hello World only to the user "foo" 
_toServer.println("USERS|GET"); //Request a list of all Connected Users 


//Example In the Recieved Message Method where all The Server Messages Get Analyzed 
serverMessage = _fromServer.readLine(); //Reads the Server Messages 

String action = serverMessage.split("|")[0]; 

if (action.equals("USERS")) { //Example "USERS|2|foo;bar" 
    String users[] = serverMessage.split("|")[2].split(";"); 
} 
if (action.equals("MESSAGE")) { //Example "MESSAGE|Hello World|PRIVATE|foo" 
    if(serverMessage.split("|")[2].equals("ALL") { 
     //Code and else for private.... 
    } 
} 
if (serverMessage.equals("STATUS|ONLINE")) { 
    // Code 
    // I leave out //Code and } for the next If statements 
} 
if (serverMessage.equals("STATUS|OFFLINE")) { 
if (serverMessage.equals("AUTH|ACCEPTED")) { 
if (serverMessage.equals("AUTH|REJECT")) { 

這是方法的正常進行?廣告你看我需要發送與代碼對應的狀態碼和對象。香港專業教育學院思想以字節爲藏漢寫入數據,並實現了「爲每個對象解碼器」,例如:

int action = _fromServer.readInt();  

//opcodes is just an Enum Holding the corresponding int 

switch(action) { 
    case(opcodes.MESSAGE): 
    break; 
    case(opcodes.AUTH): 
    break;   
} 

注意,這是更比一般的設計問題不只是這個聊天服務器實例,我認爲,即時通訊實現一個基於網絡的控制檯遊戲只是爲了練習。

有沒有更好的方法來做到這一點,甚至是一個API /框架?

在此先感謝!

回答

2

本質上你正在設計一個協議。有很多通信協議可以處理這個問題,想到的主要是IRC。我相信你可以在網上搜索關於如何實現協議的提示。

至於擴展控制檯遊戲這樣的東西,以及我將開始實施IRC,並用它來了解如何編寫真正的通信協議。一旦你完成了,你可以在它上面添加你自己的命令到你的框架中。

+0

感謝您的快速答案,我已經搞砸了幾個遊戲,這有一個Documented Protocoll和那些總是像我的第二個例子,第一個4/8字節是行動代碼,其餘的數據如下。我希望有一些東西像接口一樣在對象上實現,以便能夠將em轉換成這樣的協議形式 – Angelo 2012-02-27 10:59:35

1

我認爲Apache MINA會幫助你。 http://mina.apache.org/

構建Java C/S應用程序非常複雜,您需要處理TCP,UDP和多線程編程; MINA可以幫助你做這些事情。

我認爲你需要的其他部分是你的私人聊天協議,但是像Jabber這樣的開源IM服務怎麼樣? :)

+0

感謝MINA鏈接生病看看它!這聽起來好像這是我所搜索的。我沒有計劃啓動一個聊天服務器,它只是爲了練習和理解在任何上下文中的TCP通信如何以正確的方式完成。對我來說,複雜的部分是協議 – Angelo 2012-02-27 11:07:55

2

如果您正在設計一個語言間通信協議,我會建議不要使用格式化字符串作爲通信手段,而是使用狀態字節。例如,如果考慮TCP/IP本身的設計,您會發現,消息由固定格式頭和可變有效載荷組成。這樣你就可以知道,(例如)消息的第三個字節包含消息類型,第五個字節表示errorstate等等。這使得處理更容易。

如果你設計了你的協議,你可以考慮在java端使用顯式的MessageObjects,在這種情況下,你將實現一個工廠,爲這些對象實現編組和解組方法,將對象從協議中的消息轉換爲消息。

如果你全是java,你甚至可以省下那些努力並在客戶端和服務器上使用ObjectInputStreams和ObjectOutputStreams。如果你不是,你可能想看看谷歌協議緩衝區:http://code.google.com/intl/de-DE/apis/protocolbuffers/,這對於語言間通信基本上是一樣的。

2

如果你的項目增長了,你可能想看看Netty--這是一個處理通信代碼的框架。如果你的代碼很簡單,那麼手動操作會更好。

至於協議設計,它取決於什麼對您最重要:性能,可擴展性,可讀性,易於調試等。這些標準可能會在一定程度上相互抵觸,例如高性能可能意味着偏好二進制協議,但這些對調試的輕鬆性以及有時可擴展性都有負面影響。不要重新發明輪子通常是個好主意。獲取現有協議的啓發。如果你選擇二進制,除非你真的必須從頭開始,從Protocol Buffers開始。如果您的應用程序很簡單並且不是針對高性能,請使用人類可讀的協議,這將使您的生活更輕鬆(可使用標準外殼工具(如stracenc)進行調試和測試。