【问题标题】:Java NIO - problems with receiving data using SocketChannelsJava NIO - 使用 SocketChannels 接收数据的问题
【发布时间】:2011-04-18 23:35:56
【问题描述】:


我正在使用 Java NIO 编写简单的即时通讯工具。除了客户端没有收到已登录联系人的消息外,它工作正常。
这是主要的服务器进程方法:

public void process() throws IOException, ClassNotFoundException{
    while (true){
        selector.select();
        Set keys = selector.selectedKeys();
        Iterator it = keys.iterator();
        while (it.hasNext()){
            SelectionKey key = (SelectionKey)it.next();
            it.remove();
            if (key.isAcceptable()){
                /*configuring incoming channel to be non-blocking 
                and adding it to the clients set*/
            }
            if (key.isReadable()) {
                SocketChannel client = (SocketChannel)key.channel();
                /*Message class contains its type, source user name and data.
                getMessage() method reads message from SocketChannel*/
                Message m = getMessage(client);    
                switch (m.getType()) {
                    case LOGIN_REQUESTED:
                        /*Accept or reject the client log in name
                        in case of accepting add user with its status
                        to Map users*/
                        break;
                    case CONTACTS_REQUESTED:
                        /*Here is the problem, client gets only one message
                        sendMessage() writes the buffer with serialized 
                        message to clients channels*/
                        for (String name : users.keySet()) {
                            sendMessage(client, MessageType.CONTACTS_REQUESTED, 
                                name, users.get(name).toString());
                        }
                        break;
                   //Other messages are processing
                }
            }
        }
    }
}

处理传入消息的客户端方法:

private void processIncomingMessages() 
    throws IOException, ClassNotFoundException {
    ByteArrayInputStream bais;
    ObjectInputStream ois;
    ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
    while (true){
        selector.select();
        Set keys = selector.selectedKeys();
        Iterator it = keys.iterator();
        while (it.hasNext()){
            SelectionKey key = (SelectionKey)it.next();
            it.remove();
            if (key.isReadable()){
                SocketChannel sc = (SocketChannel)key.channel();
                buffer.clear();
                if (sc.read(buffer) != -1){
                    buffer.flip();
                    bais = new ByteArrayInputStream(buffer.array());
                    ois = new ObjectInputStream(bais);
                    Message m = (Message)ois.readObject();
                    /*My castom event serves to notify GUI to update 
                    its contact list. In case of sending CONTACTS_REQUESTED 
                    messages, it gets only one (first?) of them*/
                    fireNetworkEvent(m);
                }
            }
        }
    }
}

单独发送的其他消息毫无问题地到达客户端。 如果有任何问题,请询问。任何帮助将不胜感激

【问题讨论】:

  • 您发布的代码无法回答。您应该将其缩减为一个演示问题的小代码示例。您甚至可能会发现这样做的问题。

标签: java networking nio


【解决方案1】:

我的猜测是在客户端...

 if (sc.read(buffer) != -1){

不保证阅读您的全部信息,它可能什么也不阅读,其中一些或多条信息。

套接字是字节流,如果你想读取一个数据包(就像你做的那样),你需要对流进行打包。

一种方法是预先添加数据包的长度,并确保在尝试处理之前读取整个数据包。

另一种方法是写入数据包,使其具有唯一的终止符,您可以读取该终止符直到获得终止符。

【讨论】:

  • 正确。他假设他已经阅读了整条消息,没有证据。
猜你喜欢
  • 1970-01-01
  • 2011-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-05
  • 1970-01-01
相关资源
最近更新 更多