簡體   English   中英

使InputStream成為非阻塞

[英]Make InputStream non-blocking

目前,我有一台服務器偵聽連接(這是我擁有的移動游戲的基本高分服務器),每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)不會被阻塞。 當前套接字設置為500毫秒超時,我的服務器可以正常運行。 我的問題是,如果有人嘗試創建自己的程序進行連接以嘗試破解自己的高分或ddos服務器,則它將被一堆無用的連接所困擾,這些連接在不寫入時會阻塞線程500ms。

您可以嘗試這樣的事情。 每次調用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),直到確定地讀取了完整的字節數組,該方法才返回。 即使發件人發送了完整的數據塊(由於網絡數據包大小等),常規讀取也總是可以“返回短”。

有兩種用Java實現服務器的經典方法。

第一種也是最古老的方法是為每個連接的客戶端使用讀/寫線程對。 對於沒有大量客戶端連接的小型服務器,這是可以的,因為每個客戶端都需要兩個線程來管理它。 它不能很好地擴展到許多並發客戶端。

第二種更新的方法是使用java.nio.ServerSocketChanneljava.nio.SocketChanneljava.nio.Selector 這三個類使您可以管理在單個線程中連接的每個客戶端的所有IO操作。 是一個有關如何使用java.nio包實現非常基本的服務器的示例。

實施服務器的更好方法是使用第三方框架。 我過去使用過的一個很棒的庫是Netty 它處理套接字的所有細節,並提供了一個相當干凈和簡單的api,可以很好地擴展。

你不能 InputStreams正在阻塞。 期。 很難看到非阻塞模式將如何真正解決您提到的問題。 我建議重新設計。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM