简体   繁体   English

区分从CLIENT和其他发送的消息

[英]Distinguish between messages sent from CLIENT and other

I am using SocketChannel and Selector to write a server. 我正在使用SocketChannelSelector编写服务器。 The servers job is to allow clients to connect, read messages from clients and write messages to clients. 服务器的工作是允许客户端连接,从客户端读取消息以及将消息写入客户端。

I am having some difficulty distinguishing between messages sent from the client, and other data that's firing off the read instruction. 我很难区分客户端发送的消息和触发读取指令的其他数据

ex. 恩。 When a client connects, I noticed the read instruction is executed, without the client having sent any data. 当客户端连接时,我注意到读取指令已执行,而客户端未发送任何数据。 This is important, because after the server has read a message from the client, it must add that message to a message queue . 这很重要,因为服务器从客户端读取一条消息后,必须将该消息添加到消息队列中 These message will be removed and processed from the queue by an external application. 这些消息将被外部应用程序从队列中删除和处理。 The problem is, that every time the read fires, these yet UFM (unidentified messages) are breaking the external application when trying to decode them. 问题在于,每次触发读取时,这些尚未使用的UFM(未识别消息)就会在尝试对其进行解码时破坏外部应用程序。

I am sorry if this question has already been answered I couldn't find a complete answer. 很抱歉,如果这个问题已经回答,我找不到完整的答案。

Here is my accept method that, if I am not mistaken, tells the selector to notify us when data is available to read. 这是我的接受方法,如果我没有记错的话,它会告诉选择器在可以读取数据时通知我们。

private void accept(SelectionKey key) throws IOException {
    ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();

    // Accept the connection and make it non-blocking
    SocketChannel socketChannel = serverSocketChannel.accept();
    socketChannel.configureBlocking(false);

    socketChannel.register(this.selector, SelectionKey.OP_READ);
}

Here is the selector method which waits for an event. 这是等待事件的选择器方法。

while (should_run) {
    try {
        //Load all pending operations to key
        while (!operations.isEmpty()) {
            SelectionKey key = client.keyFor(getSelector());
            if (!key.isValid()) {
                operations.remove();
                throw new Exception("Key not valid");
            }
            key.interestOps(operations.remove());
        }

        selector.select();

        Iterator selectedKeys = selector.selectedKeys().iterator();
        while (selectedKeys.hasNext()) {
            SelectionKey key = (SelectionKey) selectedKeys.next();
            //Check if key is valid
            if (!key.isValid()) {
                throw new Exception("Key not valid");
            }

            if (key.isAcceptable()) {
                accept(key);
            } else if (key.isReadable()) {
                read(key);
            } else if (key.isWritable()) {
                write(key);
            }

            selectedKeys.remove();
        }
    } catch (Exception e) {
        System.err.println("Something went wrong: " + e.getMessage());
        e.printStackTrace();
    }
}

Here is the read function, called if key.isReadable() 这是读取函数,如果key.isReadable()被调用

private void read(SelectionKey key) {     
    System.out.println("Read fired");

    //Clear the buffer for new Data
    this.readBuffer.clear();

    int count;
    try {
        count = this.client.read(this.readBuffer);
        if (count == -1) {
            throw new IOException("Socket closed");
        }
    } catch (IOException e) {
        key.cancel();
        return;
    }

    //PROBLEM OCCURRING HERE
    this.worker.give(this.readBuffer.array(), count);
}

The read should read messages, and hand the message to a worker thread, where the message is decoded and other nice things happen to it. 读取应该读取消息,并将消息传递给工作线程,在该线程中对消息进行解码,并发生其他事情。

The read method is called after each connection of a new client. 在每次新客户端连接后都会调用read方法。 The count is usually small, between 4 and 10 and when I decode using new String(data[], "UTF-8") , it turns out to be Japanese or something.. 该计数通常很小,在4到10之间,当我使用new String(data[], "UTF-8")解码时,结果证明是日语或其他类型。

I tested this by simply printing the count every time the read is called. 我通过在每次调用读取时简单地打印count测试这一点。

This problem can be solved by simply checking the size of each incoming message and ignoring those which are to small. 通过简单地检查每个传入消息的大小并忽略那些较小的消息,可以解决此问题。 But this seems like it could backfire if fragmentation occurs. 但是,如果出现碎片,这似乎可能适得其反。

EDIT: Client example code: 编辑:客户端示例代码:

Socket socket = new Socket("localhost", 3000);
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
while (true) {
    String input = JOptionPane.showInputDialog("Send something to the server");
    if (input == null)
            break;
    oos.writeObject(input);
}

NOTE: I don't have the source code for the peer, but this VERY SIMPLE example yields the exact same results. 注意:我没有同级的源代码,但是这个非常简单的示例产生的结果完全相同。 Before the MessageDialog even prompts for a message to send to the server, a message is received by the server, which is either Japanese or a series of question marks (?? ???). 在MessageDialog甚至提示将消息发送到服务器之前,服务器已收到一条消息,该消息可以是日语或一系列问号(?????)。

and other data that's firing off the read instruction. 以及触发读取指令的其他数据。

There is no 'other data'. 没有“其他数据”。 Only data from the client. 仅来自客户端的数据。

'new ObjectOutputStream()' writes a stream header that starts with 0xAC. “ new ObjectOutputStream()”写入以0xAC开头的流头。 That's what you're reading. 那就是你正在读的书。

As the peer is using object streams you should be using blocking sockets, threads, and object input streams. 当对等方使用对象流时,您应该使用阻塞套接字,线程和对象输入流。 Not NIO. 不是NIO。

The 'this.client' member should be removed as per my comments above. 我上面的评论应删除“ this.client”成员。 It assumes you only have one client. 假设您只有一个客户。

Closing the channel cancels the key. 关闭通道会取消该键。 You rarely if ever need key.cancel(). 您很少需要key.cancel()。 I never use it. 我从不使用它。

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

相关问题 如何解析从 IoT 客户端发送到 Aws Thing 的消息 - How to parse the messages sent from IoT Client to the Aws Thing XMPP-Facebook-我的客户端实现如何接收其他客户端实现发送的消息? - XMPP - Facebook - How can my client implementation receive messages sent by other client implementations? Java - 在客户端识别来自服务器的发送对象和发送到所有消息 - Java - Recognise sent-to-one and sent-to-all messages from server, on the client-side Java:客户端发送的消息与服务器接收的消息之间存在差异 - Java: discrepancy between message sent from client and message received at server 邮件仅发送给在我的聊天程序中发送邮件的客户端 - Messages are only being sent to the client that sent them in my chat program Java TCP客户端未收到从C#服务器发送的消息 - Java TCP Client doesn't receive messages sent from C# Server Cloudhopper SMPP - 如何获取从其他客户端发送的消息内容? - Cloudhopper SMPP - How to get messages content which have sent from other clients? 我的POP3服务器正在向我发送已发送和已接收的消息-如何最终区分 - My POP3 sever is sending me both sent and received messages - how to conclusively distinguish 从客户端接收消息 - Receiving messages from Client 区分多个键盘上的按键事件 - Distinguish between key events from multiple keyboards
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM