我大部分时间都在使用 Netty,但有一个概念仍在暗示我,而且我在教程等中找不到任何内容。首先,我确实理解 Netty 是异步的,但客户端必须有一种方法可以调用服务器并能够获得处理程序之外的响应。让我解释更多。
我有一个客户,如下图所示。请注意,我知道它是自举的,每次调用都会建立一个新连接,这只是为了让示例更小、更简洁。请忽略这个事实。
客户端.java
// ServerResponse is a result from the server, in this case
// a list of users of the system (ignore that each time it's all bootstrapped).
public User[] callServerForInformationFromGUIWidget()
{
ClientBootstrap bootstrap = new ClientBootstrap(...);
bootstrap.setPipelineFactory(...);
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
Channel channel = future.awaitUninterruptibly().getChannel();
// Where request is a POJO sent to the server,
// with a request such as get me a list of users
RequestPojo request = new RequestPojo(requestUserListCommand);
ChannelFuture lastWriteFuture = channel.write(request);
if(lastWriteFuture != null)
lastWriteFuture.awaitUninterruptibly();
}
现在我明白了如何获取服务器上的数据,并返回结果。唯一的问题是我如何在客户端处理它?是的,clientHandler 类可以执行如下操作:
客户端处理程序.java
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
{
User[] users = (User[])e.getMessage();
}
问题是客户端代码实际上是如何得到那个结果的?所有示例都类似于聊天服务,其中事件触发客户端上不等待响应的其他内容。即使是我发现的 http 客户端示例也缺少这个。整体文档非常好,但缺少如何进行回调。无论如何,在这种情况下,我需要客户端从服务器获取响应,并根据结果执行所需的操作。
换句话说,我该如何编写客户端来做这样的事情:
理想客户端.java
// ServerResponse is a result from the server, in this case
// a list of users of the system.
public User[] callServerForInformationFromGUIWidget()
{
...
RequestPojo request = new RequestPojo(requestUserListCommand);
ChannelFuture lastWriteFuture = channel.write(request);
if(lastWriteFuture != null)
lastWriteFuture.awaitUninterruptibly();
User[] users = resultFromCallToServer();
performSomeAction(users);
}
因为处理者不知道是谁在寻找答案,或者是谁提出了问题。如果它是在处理程序中完成的,那么怎么做呢?
回到我对示例的评论,http 客户端(和处理程序)示例只是将结果转储到 System.out。如果您有 GUI,您将如何将请求的结果传递给 GUI?我从未见过这方面的任何例子。
最佳答案
杰斯坦是正确的。在我的例子中,我有一个需要处理价格变动数据的客户。我使用 Antlr 进行解析。我在我的解析器中触发我的事件,但在我的例子中,我的协议(protocol)是基于字符串的。下面是一个没有 Antlr 的例子,我在你的情况下传递了字符串消息,它可能是用户。
//----------------- Event --------------
public class DataChangeEvent {
private String message;
public DataChangeEvent(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
//----------------- Listener --------------
public interface DataChangeListenter {
public void dataChangeEvent(DataChangeEvent event);
}
//----------------- Event Handler that fires the dataChange events --------------
// This class needs to be static since you need to register all your classes that want to be notified of data change events
public class DataChangedHandler {
private static List<DataChangeListenter> listeners = new ArrayList<DataChangeListenter>();
public static void registerDataChangeListener(DataChangeListenter listener) {
listeners.add(listener);
}
public static void fireDataChange(DataChangeEvent dataChangeEvent) {
for(DataChangeListenter listenter : listeners) {
listenter.dataChangeEvent(dataChangeEvent);
}
}
}
//----------------- Example class that implements the listener and registers itself for events --------------
public class ProcessMessage implements DataChangeListenter {
public ProcessMessage() {
DataChangedHandler.registerDataChangeListener(this);
}
public void dataChangeEvent(DataChangeEvent event) {
//Depending on your protocal, I use Antlr to parse my message
System.out.println(event.getMessage());
}
}
//---------------- Netty Handler -----------
public class TelnetClientHandler extends SimpleChannelHandler {
private static final Logger logger = Logger.getLogger(TelnetClientHandler.class.getName());
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
String message = (String) e.getMessage();
DataChangedHandler.fireDataChange(message);
}
}
关于java - Netty - 如何在客户端获取服务器响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9048701/