简体   繁体   English

Java套接字:通过套接字将请求推送到客户端

[英]Java socket: Pushing requests to client through socket

I'm currently making a client-server application which primarily is built to make procedure call to a server and wait for a packet response. 我当前正在制作一个客户端-服务器应用程序,该应用程序主要用于对服务器进行过程调用并等待数据包响应。

however i would like to make the server 'push' news out to the client (at a spontaneous time), but that seems to be a problem if the message arrives when the client listens for another packet response. 但是,我想让服务器(自发地)向客户端“推送”新闻,但是如果客户端侦听另一个数据包响应时消息到达,这似乎是一个问题。

Is there a way to split a socket into 2 unique channel streams, through the same socket instance? 是否可以通过同一套接字实例将套接字拆分为2个唯一的通道流? Or would it be better to make a client thread which only listens for incoming connections and dispatches them to a queue? 还是使一个客户端线程仅侦听传入的连接并将其分派到队列中会更好?

What are some common patterns and practices when working with 2-way client-server connection? 使用双向客户端-服务器连接时,有哪些常见的模式和做法? (Where streams occur spontaneous) (自发出现的地方)

For reminders i'm using Java Socket, ObjectInputStream and ObjectOutputstream. 为了提醒我,我使用Java Socket,ObjectInputStream和ObjectOutputstream。 i'm not using Java RMI. 我没有使用Java RMI。

So one of the things you'll come up against when learning about networking is loss of synchronization. 因此,在学习网络时会遇到的一件事就是失去同步。 This happens when you 'hard-code' a certain set of client-server interactions, for example; 例如,当您“硬编码”一组特定的客户端-服务器交互时,就会发生这种情况。

server sends 2 byte status code
client receives 2 byte status code
client responds with 4 byte operation code

If for some reason there is a bug that causes any part of this interaction to not happen precisely as it needs to, then the rest of the program fails because all network interaction is now out of sync. 如果由于某种原因存在一个错误,导致该交互的任何部分均未按需要准确发生,则该程序的其余部分将失败,因为现在所有网络交互都不同步。 The client might read a set of bytes that it believes represents a string, when really the server is sending an int, and so on. 当服务器确实发送int时,客户端可能会读取它认为代表字符串的一组字节,依此类推。 Worst of all you might find that your main network threads deadlock because both client and server are waiting for input at the same time. 最糟糕的是,您可能会发现主网络线程陷入僵局,因为客户端和服务器都在同时等待输入。

With a larger project, where there are certainly bugs, this will happen an awful lot if you code in this style. 在一个较大的项目中,肯定有很多错误,如果您使用这种风格进行编码, 则会发生很多事情。 For this reason, we have something called middleware . 因此,我们有一个叫做Middleware的东西。

A very common and flexible middleware paradigm is the TLV Message Protocol . TLV消息协议是一种非常常见且灵活的中间件范例。 You would implement some simple classes (in semi-java-pseudocode); 您将实现一些简单的类(使用准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
        }
    }

Now you have two threads running on the client, and two threads running on the server. 现在,您在客户端上运行了两个线程,在服务器上运行了两个线程。 Each end has its own Pusher and Reader . 每个端都有自己的PusherReader The important thing to note is that because you write the length field to the output stream, the reader always knows how many bytes it needs to read. 需要注意的重要一点是,因为您将length字段写入输出流,所以读取器始终知道需要读取多少字节。 So even if one message has been serialised incorrectly, its length is still correct and the next message will always be read correctly from the first byte to the last. 因此,即使一个消息被错误地序列化了,它的长度仍然是正确的,并且下一条消息将始终从第一个字节到最后一个字节被正确读取。 This way your program can never go out of sync. 这样,您的程序就永远不会失去同步。

You simply add TLVMessage objects to the pusher.queue , and they will arrive at the reader.queue on the other end of the socket. 您只需将TLVMessage对象添加到pusher.queue ,它们将到达套接字另一端的reader.queue You can then handle the messages (in another, third, thread which watches reader.messages.size() ) by their type field. 然后,您可以按消息的type字段处理消息(在另一个reader.messages.size()线程中)。

You do not need to worry about what order things happen in, you have a robust mechanism for passing messages between client and server, in two directions. 您无需担心事情发生的顺序,您有一个健壮的机制可以在两个方向上在客户端和服务器之间传递消息。 You have abstracted away the fiddly network stuff, and can just get on with coding. 您已经抽象了一些杂乱无章的网络内容,并且可以继续进行编码。

There are, of course, libraries that do all this for you, but it's always worth understanding the how and the why in my opinion. 当然,有图书馆为您完成所有这些工作,但是我认为始终值得了解如何以及为什么这样做。

Do you have to code directly to sockets? 您是否必须直接向套接字编码? It sounds like a good candidate to go higher in the OSI stack and use eg. 听起来像是在OSI堆栈中更高并使用例如的好候选人。 JMS to achieve your goal. JMS实现您的目标。

Hope that helps. 希望能有所帮助。

Cheers, 干杯,

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM