2012-02-27 62 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)进行调试和测试。