首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用javanio从阻塞转换为非阻塞I/O

用javanio从阻塞转换为非阻塞I/O
EN

Stack Overflow用户
提问于 2011-03-28 13:33:41
回答 2查看 1.3K关注 0票数 0

我调整了这个代码How to send and receive serialized object in socket channel,我的实时模拟用来发送对象,但是我遇到了一个又一个的异常,这是因为这种代码阻塞在本质上是如何用javanio将代码转换为非阻塞的。

代码语言:javascript
复制
  /*
     * 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 CleanSender implements Runnable {

        private SimManager SM;
        private BallState ballState = new BallState(10, 5);
        private ServerSocketChannel ssChannel;

        private Thread tRunSer = new Thread(this, "ServerSelectThread");

    public static void main(String[] args) throws IOException {

        CleanSender server = new CleanSender();
        server.startServer();

    }

    private void startServer() throws IOException {
        ssChannel = ServerSocketChannel.open();
        ssChannel.configureBlocking(true);
        int port = 2345;
        ssChannel.socket().bind(new InetSocketAddress(port));
        // SM = new SimManager(this, BS);
        // SM.start(); // GameEngine thread starting here
        tRunSer.start();
    }

    public void run() {
        try {
            SocketChannel sChannel = ssChannel.accept();

            while (true) {

                ObjectOutputStream oos = new ObjectOutputStream(sChannel
                        .socket().getOutputStream());
                oos.writeObject(ballState);
                System.out.println("Sending String is: '" + ballState.X + "'" + ballState.Y);
                oos.close();
                System.out.println("Sender Start");
                System.out.println("Connection ended");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Client:它一直在寻找服务器的回复。

代码语言:javascript
复制
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.InetSocketAddress;
import java.nio.channels.SocketChannel;

public class CleanReceiver implements Runnable {

    private SocketChannel sChannel;
    private Thread receiverThread = new Thread(this, "receiverThread");


    private synchronized  void startServer() throws IOException {
         sChannel = SocketChannel.open();
         sChannel.configureBlocking(true);
         if (sChannel.connect(new InetSocketAddress("localhost", 2345))) {
             receiverThread.start();
         }
    }
public void run() {

    while (true) {
        try {
            ObjectInputStream ois = new ObjectInputStream(sChannel.socket()
                    .getInputStream());

            BallState s = (BallState) ois.readObject();
            System.out.println("String is: '" + s.X + "'" + s.Y);
            ois.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

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


      public static void main(String[] args) 
        throws IOException, ClassNotFoundException {

            CleanReceiver rc=new CleanReceiver();
            rc.startServer();

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

当服务器必须保持连接客户端并同时将模拟状态发送到已经连接的客户端时,会在这种情况下工作吗?,我正在寻找专家的目光。

谢谢,

吉比拉

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-03-28 14:30:37

您的代码有两个主要问题:

  • 您在处理每个对象之后关闭流,这会导致关联套接字的关闭,因此它们不再有效,不能用于处理以下对象。在接收端,您根本不需要循环中的close(),在发送端使用flush()而不是close()来确保缓冲区被刷新。在实现阻塞IO时,
  • (通常)需要为每个客户端在服务器上启动一个新线程。它将允许您与多个客户同时通信。请注意本例中的线程同步问题!

如果每个客户端都有一个线程是不可接受的,您可以以非阻塞的方式实现服务器,但是,正如Peter已经说过的那样,它更复杂,所以我建议您首先让它使用阻塞IO。

票数 0
EN

Stack Overflow用户

发布于 2011-03-28 13:47:16

如果您正在使用ObjectInputStream或ObjectOutputStream,我建议您继续使用阻塞IO。在这些库中使用非阻塞IO是实际收益的10倍。

您是否考虑过使用ServerSocketSocket而不是NIO。这些将更容易使用,而对象流的来源都是设计用来使用的,

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5459750

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档