在过去的几天里,我一直在使用TCP/IP通信(使用Java和C#)。我知道它是如何工作的,并且能够使用它。我的问题更多的是一个代码设计问题,它是如何做到最好和最简单的方式来进行真正的沟通。
例如,我构建了自己的多用户聊天服务器。我希望我的通讯能够决定它是一个身份验证请求,还是一个新的聊天消息,获得当前用户列表的能力等。
我自己实现了一些方法,但我对此并不是很满意,因为我认为有一种更标准、更美观的方法来实现它。
我首先想到的是一个带有分隔符的字符串,下面是我在Java中实现My Communication的示例:
//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")) {这是它通常的方式吗?你看,我需要发送状态代码和代码对应的对象。我也考虑过将数据写入Bytes,并实现一个“每个对象的解码器”,例如:
int action = _fromServer.readInt();
//opcodes is just an Enum Holding the corresponding int
switch(action) {
case(opcodes.MESSAGE):
break;
case(opcodes.AUTH):
break;
}请注意,这是更多的一般设计问题,而不仅仅是这个聊天服务器的例子,我认为我实现了一个小的网络为基础的控制台游戏只是为了练习。
有没有更好的方法来做这件事,甚至是API/框架?
提前感谢!
发布于 2012-02-27 18:52:23
从本质上讲,你是在设计一个协议。有许多通信协议可以处理这一点,我想到的主要协议是IRC。我相信你可以在网上搜索一下关于如何实现这个协议的提示。
至于将这样的东西扩展到控制台游戏,那么我将从实现IRC开始,并使用它来学习真正的通信协议是如何编写的。完成后,您可以在此基础上构建,以便将您自己的命令添加到您的框架中。
发布于 2012-02-27 19:38:51
如果您正在设计一个用于跨语言通信的协议,我建议不要使用格式化字符串作为一种通信方式,而是使用statusbytes。例如,如果您考虑TCP/IP本身的设计,您会发现,消息由固定格式的报头和可变有效负载组成。这样你就会知道,(例如)消息的第三个字节包含messagetype,第五个字节表示错误状态,依此类推。这使得处理变得更容易。
如果你已经设计了你的协议,你可以考虑在Java端使用显式的MessageObjects,在这种情况下,你可以为这些对象实现一个带有编组和解组方法的工厂,将对象从你的协议中的消息转换为消息。
如果您是纯java开发人员,您甚至可以省去这方面的工作,在客户端和服务器端使用ObjectInputStreams和ObjectOutputStreams。如果不是这样,您可能想看看Google Protocol Buffers:http://code.google.com/intl/de-DE/apis/protocolbuffers/,它在跨语言通信方面基本上做了同样的事情。
发布于 2012-02-27 19:39:38
如果你的项目在增长,你可能想看看Netty --它是一个处理通信代码的框架。如果你的代码很简单,你最好手动完成。
至于协议设计,这取决于对你来说最重要的是什么:性能、可扩展性、人类可读性、调试简易性等。这些标准可能在某种程度上相互矛盾,例如,高性能可能意味着优先选择二进制协议,但这些都会对调试的简易性产生负面影响,有时还会影响可扩展性。通常,不要重复发明轮子是个好主意。从现有协议中获得灵感。如果你选择二进制,不要从头开始,除非你真的必须这样做,从Protocol Buffers开始。如果您的应用程序很简单,并且不以高性能为目标,请使用人类可读的协议,这将使您的工作变得更容易(使用标准的外壳工具,如strace和nc,可以进行调试和测试)。
https://stackoverflow.com/questions/9463706
复制相似问题