如何在套接字通道中发送和接收序列化对象

29

我想通过套接字通道传输一个序列化对象。 我想将“Hi friend”字符串作为序列化对象,然后在将该对象写入套接字通道时,在另一端我想读取相同的对象并检索数据。

我想使用Java的SocketChannel完成所有这些操作。如何实现? 我已尝试像下面这样做,但在接收端没有获取到任何数据。

private static void writeObject(Object obj, SelectionKey selectionKey) {
    ObjectOutputStream oos;
    try {
        SocketChannel channel = (SocketChannel) selectionKey.channel();
        oos = new ObjectOutputStream(Channels.newOutputStream(channel));

        oos.writeObject(obj);
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

private static Object readObject(SelectionKey selectionKey) {
    ObjectInputStream ois;
    Object obj = new Object();
    SocketChannel channel = (SocketChannel) selectionKey.channel();
    try {
        ois = new ObjectInputStream(Channels.newInputStream(channel));
        obj = ois.readObject();
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return obj;
}

问题丢失了! - tuergeist
你的 SocketChannel 已经打开并连接了吗? - tuergeist
是的,套接字通道已经打开并连接。 - Sunil Kumar Sahoo
1个回答

38

您的SocketChannel处理似乎不完整,可以查看此处有关使用SocketChannels传输字节的完整示例:

/*
 * Writer
 */
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.InetSocketAddress;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

public class Sender {
    public static void main(String[] args) throws IOException {
        System.out.println("Sender Start");

        ServerSocketChannel ssChannel = ServerSocketChannel.open();
        ssChannel.configureBlocking(true);
        int port = 12345;
        ssChannel.socket().bind(new InetSocketAddress(port));

        String obj ="testtext";
        while (true) {
            SocketChannel sChannel = ssChannel.accept();

            ObjectOutputStream  oos = new 
                      ObjectOutputStream(sChannel.socket().getOutputStream());
            oos.writeObject(obj);
            oos.close();

            System.out.println("Connection ended");
        }
    }
}

还有一个阅读器

/*
 * Reader
 */
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.InetSocketAddress;
import java.nio.channels.SocketChannel;

public class Receiver {
    public static void main(String[] args) 
    throws IOException, ClassNotFoundException {
        System.out.println("Receiver Start");

        SocketChannel sChannel = SocketChannel.open();
        sChannel.configureBlocking(true);
        if (sChannel.connect(new InetSocketAddress("localhost", 12345))) {

            ObjectInputStream ois = 
                     new ObjectInputStream(sChannel.socket().getInputStream());

            String s = (String)ois.readObject();
            System.out.println("String is: '" + s + "'");
        }

        System.out.println("End Receiver");
    }
}

当你首先启动服务器,接着再启动接收器时,你会得到以下输出:

服务器的控制台

Sender Start
Connection ended

接收者的控制台

Receiver Start
String is: 'testtext'
End Receiver

这并不是最佳解决方案,但它遵循了您使用Java的ServerSocketChannel的方式。


1
“不是最佳解决方案”是什么意思?您能详细说明一下吗?另外,如果您在通道周围包装一个流,是否会失去NIO的性能?谢谢! - Jeach
性能不是正确的词。我的意思是,我尝试将上面的代码合并到我的现有“非阻塞”NIO代码中,但是我遇到了“java.nio.channels.IllegalBlockingModeException”异常。你有解决方法或“更好的解决方案”吗? - Jeach
1
嗨,a)以上代码仅适用于阻塞。b)我不想详细解释更好的解决方案,您应该提出单独的问题来回答。另外,总有更好的解决方案。 - tuergeist

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接