使InputStream无阻塞

时间:2015-01-28 02:54:13

标签: java inputstream nonblocking

目前我有一个侦听连接的服务器(它是我手机游戏的基本高分服务器),每1000毫秒循环连接并侦听任何传入数据。

public void readData(Connection c) throws IOException {
    PacketBuffer readBuffer = new PacketBuffer(Server.PACKET_CAPACITY);
    int packetSize = c.getIn().read();
    c.getIn().mark(packetSize);
    byte[] buffer = new byte[packetSize];
    c.getIn().read(buffer, 0, buffer.length);
    readBuffer.setBuffer(buffer);
    packetHandler.addProcess(c, readBuffer);
}

我使用自己的PacketBuffer,我需要找到一种方法,以便c.getIn()。read()(这是我的连接InputStream)不会阻塞。目前套接字设置为500ms超时,我的服务器将以这种方式正常运行。我的问题是,如果有人试图让他们自己的程序连接尝试并破解他们自己的高分或服务器它会变得错综复杂的一堆无用的连接,当连接没有写入时阻塞线程500ms一块。

3 个答案:

答案 0 :(得分:3)

你可以尝试这样的事情。每次调用 readData 时,它都会检查字节是否可供读取。我在这里使用 while 循环,因为您希望它在线程再次休眠之前处理它可以处理的所有数据。这将确保消息不会被备份,如果它只是每x毫秒读一个。

public void readData(Connection c) throws IOException {
    while (c.getIn().available() > 0) {
        int packetSize = c.getIn().read();
        c.getIn().mark(packetSize);
        byte[] buffer = new byte[packetSize];
        c.getIn().read(buffer, 0, buffer.length);
        PacketBuffer readBuffer = new PacketBuffer(Server.PACKET_CAPACITY);
        readBuffer.setBuffer(buffer);
        packetHandler.addProcess(c, readBuffer);
    }

我不知道你为什么使用mark方法。看起来对我有问题。

您还需要使用readFully()样式方法(请参阅DataInputStream),该方法在确定读取完整字节数组之前不会返回。即使发送方已发送完整数据块(由于网络数据包大小调整等),常规读取也总是“返回短路”。

答案 1 :(得分:2)

在java中实现服务器有两种经典方法。

第一种也是最早的方法是为每个连接的客户端使用读/写线程对。对于没有大量连接客户端的小型服务器,这是可以的,因为每个客户端都需要两个线程来管理它。它不能很好地扩展到很多并发客户端。

第二种和更新的方法是使用java.nio.ServerSocketChanneljava.nio.SocketChanneljava.nio.Selector。这三个类允许您管理在单个线程中连接的每个客户端的所有IO操作。 Here是如何使用java.nio包实现非常基本的服务器的示例。

实现服务器的更好方法是使用第三方框架。我过去使用的一个很棒的图书馆是Netty。它处理套接字的所有细节,并提供相当干净和简单的api,可以很好地扩展。

答案 2 :(得分:0)

你不能。 InputStreams正在阻塞。期。很难看出非阻塞模式将如何真正解决您提到的问题。我建议重新设计是有序的。