[英]Java socket: Pushing requests to client through socket
我当前正在制作一个客户端-服务器应用程序,该应用程序主要用于对服务器进行过程调用并等待数据包响应。
但是,我想让服务器(自发地)向客户端“推送”新闻,但是如果客户端侦听另一个数据包响应时消息到达,这似乎是一个问题。
是否可以通过同一套接字实例将套接字拆分为2个唯一的通道流? 还是使一个客户端线程仅侦听传入的连接并将其分派到队列中会更好?
使用双向客户端-服务器连接时,有哪些常见的模式和做法? (自发出现的地方)
为了提醒我,我使用Java Socket,ObjectInputStream和ObjectOutputstream。 我没有使用Java RMI。
因此,在学习网络时会遇到的一件事就是失去同步。 例如,当您“硬编码”一组特定的客户端-服务器交互时,就会发生这种情况。
server sends 2 byte status code
client receives 2 byte status code
client responds with 4 byte operation code
如果由于某种原因存在一个错误,导致该交互的任何部分均未按需要准确发生,则该程序的其余部分将失败,因为现在所有网络交互都不同步。 当服务器确实发送int时,客户端可能会读取它认为代表字符串的一组字节,依此类推。 最糟糕的是,您可能会发现主网络线程陷入僵局,因为客户端和服务器都在同时等待输入。
在一个较大的项目中,肯定有很多错误,如果您使用这种风格进行编码, 则会发生很多事情。 因此,我们有一个叫做Middleware的东西。
TLV消息协议是一种非常常见且灵活的中间件范例。 您将实现一些简单的类(使用准Java伪代码);
TLVMessage
int type;
byte[] value;
TLVPusher implements Runnable
OutputStream out;
Queue<TLVMessage> messages;
run() {
while(true) {
//poll and write front of queue to out (INCLUDING value.length!)
}
}
TLVReader implements Runnable
InputStream in;
Queue<TLVMessage> messages;
run() {
while(true) {
//read message from in and add to queue
}
}
现在,您在客户端上运行了两个线程,在服务器上运行了两个线程。 每个端都有自己的Pusher
和Reader
。 需要注意的重要一点是,因为您将length字段写入输出流,所以读取器始终知道需要读取多少字节。 因此,即使一个消息被错误地序列化了,它的长度仍然是正确的,并且下一条消息将始终从第一个字节到最后一个字节被正确读取。 这样,您的程序就永远不会失去同步。
您只需将TLVMessage
对象添加到pusher.queue
,它们将到达套接字另一端的reader.queue
。 然后,您可以按消息的type
字段处理消息(在另一个reader.messages.size()
线程中)。
您无需担心事情发生的顺序,您有一个健壮的机制可以在两个方向上在客户端和服务器之间传递消息。 您已经抽象了一些杂乱无章的网络内容,并且可以继续进行编码。
当然,有图书馆为您完成所有这些工作,但是我认为始终值得了解如何以及为什么这样做。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.