简体   繁体   English

使InputStream成为非阻塞

[英]Make InputStream non-blocking

Currently I have a server that listens for connections (it is a basic highscore server for a mobile game I have), loops through the connections every 1000ms and listens for any incoming data. 目前,我有一台服务器侦听连接(这是我拥有的移动游戏的基本高分服务器),每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);
}

I use my own PacketBuffer and I need to find a way so that c.getIn().read() (That is my connections InputStream) doesn't block. 我使用自己的PacketBuffer,我需要找到一种方法来使c.getIn()。read()(这是我的输入InputStream)不会被阻塞。 Currently the socket is set to 500ms timeout, and my server would run fine that way. 当前套接字设置为500毫秒超时,我的服务器可以正常运行。 My problem is if someone tries to make their own program to connect to try and hack their own highscores or ddos the server it will become convoluted with a bunch of useless connections that block the thread for 500ms a piece when the connection isn't writing. 我的问题是,如果有人尝试创建自己的程序进行连接以尝试破解自己的高分或ddos服务器,则它将被一堆无用的连接所困扰,这些连接在不写入时会阻塞线程500ms。

You could try something like this. 您可以尝试这样的事情。 Every time readData gets called it will check to see if bytes are available to read. 每次调用readData时,它将检查是否可以读取字节。 I used a while loop here because you want it to process all the data it can before the thread sleeps again. 这里使用了while循环,因为您希望它在线程再次休眠之前处理所有可以处理的数据。 This will ensure messages dont get backed up, if it were to only read one every x milliseconds. 如果每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);
    }

I dont know why you are using the mark method. 我不知道您为什么使用mark方法。 Looks problematic to me. 对我来说似乎有问题。

You also really need to use a readFully() style method (see DataInputStream) which won't return until it's definitely read the full byte array. 您还真的需要使用readFully()样式方法(请参见DataInputStream),直到确定地读取了完整的字节数组,该方法才返回。 Regular reads can always "return short", even when the sender has sent the full data block (due to network packet sizing etc). 即使发件人发送了完整的数据块(由于网络数据包大小等),常规读取也总是可以“返回短”。

There are two classic ways to implement servers in java. 有两种用Java实现服务器的经典方法。

The first and oldest way is to use a read/write thread pair for each connected client. 第一种也是最古老的方法是为每个连接的客户端使用读/写线程对。 This is okay for smaller servers without a lot of connected clients as each client requires two threads to manage it. 对于没有大量客户端连接的小型服务器,这是可以的,因为每个客户端都需要两个线程来管理它。 It doesn't scale very well to a lot of concurrent clients. 它不能很好地扩展到许多并发客户端。

The second and newer way is to use java.nio.ServerSocketChannel , java.nio.SocketChannel , and java.nio.Selector . 第二种更新的方法是使用java.nio.ServerSocketChanneljava.nio.SocketChanneljava.nio.Selector These three classes allow you to manage all IO operations for every client you have connected in a single thread. 这三个类使您可以管理在单个线程中连接的每个客户端的所有IO操作。 Here is an example for how to implement a very basic server using the java.nio package. 是一个有关如何使用java.nio包实现非常基本的服务器的示例。

A much better way to implement a server would be to use a third-party framework. 实施服务器的更好方法是使用第三方框架。 A great library that I have used in the past is Netty . 我过去使用过的一个很棒的库是Netty It handles all the nitty-gritty details of sockets and provides a fairly clean and simple api that scales well. 它处理套接字的所有细节,并提供了一个相当干净和简单的api,可以很好地扩展。

You can't. 你不能 InputStreams are blocking. InputStreams正在阻塞。 Period. 期。 It's hard to see how non-blocking mode would actually solve the problem you mention. 很难看到非阻塞模式将如何真正解决您提到的问题。 I suggest a redesign is in order. 我建议重新设计。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM