首页 文章

用于服务器/客户端通信的自定义readLine()方法

提问于
浏览
0

我正在编写服务器/客户端应用程序,服务器将与许多不同的客户端进行通信 . 与每个客户端的通信发生在运行服务器的机器上的单独线程中 . 到目前为止,我一直在使用BufferedReader类,以便使用readLine()方法从客户端套接字读取数据 . 我对readLine()的问题是它在找到换行符时会停止读取 . 由于我的程序的性质,我想用一个字符序列替换新的行限制,如$ ^%,所以使用readLine()调用BufferedReader将继续读取它找到的unitl&^% . 例如,如果客户端尝试发送url或文件路径,其中\ n可以作为自然路径的一部分找到,readLine()方法将读取\ n并停止进一步读取 .

我已经创建了以下类来尝试解决此问题 . 但我现在创造了一个更大的一个 . 当我使用BufferedReader类和readLine()方法时,我的服务器可以为很多客户端提供服务,但是当我使用CustomBufferedReader和readCustomLine()时,服务器在4或5个线程开始运行后崩溃 . 我很确定我的课程比readLine()消耗了大量资源,但我不知道,为什么或如何 .

我很感激有关此事的任何见解 .

public class CustomBufferedReader extends BufferedReader {

public CustomBufferedReader(Reader reader) {
    super(reader);
}


/**
 * Keeps reading data from a socket and stores them into a String buffer until
 * the combination of $^% is red.
 * 
 * @return A String containing the buffer red without the $^% ending.
 * @throws IOException 
 */
public String readCustomLine() throws IOException {


    //$^%
    String buffer="";
    try 
    {
        if(super.ready())
        {
            //First I'm reading 3 bytes in order to have at least 3 bytes
            //in the buffer to compare them later on.
            try 
            {
                buffer = buffer + (char)super.read();
                buffer = buffer + (char)super.read();
                buffer = buffer + (char)super.read();           
            } 
            catch (IOException e) 
            {
                e.printStackTrace();
                System.out.println(e.getMessage());
            }
            int i=0;
            //This while well keep reading bytes and adding the to the buffer until it reads  
            //$^% as the terminating sequence of bytes.
            while (!(buffer.charAt(i)=='$' && buffer.charAt(i+1)=='^' && buffer.charAt(i+2)=='%')){
                try 
                {
                    buffer = buffer + (char)super.read();
                    i++;
                } 
                catch (IOException e) 
                {
                    e.printStackTrace();
                    System.out.println(e.getMessage());
                }
            }

            // Returns the saved buffer after subtracting the $^% ending.
            return buffer.substring(0, buffer.length() - 3);
        }
    } 
    catch (IOException e) 
    {
        //e.printStackTrace();
    }   
    return buffer;
}


}

1 回答

  • 1

    我认为这是一种更简单的方法来实现您的目标:

    String line = new Scanner(reader).useDelimiter("$^%").next();
    

    关于为什么readCustomLine的实现不起作用,您可能会遇到并发问题 . 如果你看一下BufferedReader的readLine实现,你可能会注意到它的所有代码都运行在 synchronized 块中 . 所以你可以在你的代码中尝试一下 .

    此外,如果从super.read()抛出异常,您只需捕获它并继续运行,即使生成的缓冲区有错误,您也可以尝试删除内部的try / catch块 .

    最后,正如EJP指出的那样,你应该删除ready()调用并检查每个super.read()是否为-1(意味着EOF) .

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.Reader;
    
    public class CustomBufferedReader extends BufferedReader {
    
        public CustomBufferedReader(final Reader reader) {
            super(reader);
        }
    
        /**
         * Keeps reading data from a socket and stores them into a String buffer
         * until the combination of $^% is read.
         *
         * @return A String containing the buffer read without the $^% ending.
         * @throws IOException
         */
        public synchronized String readCustomLine() throws IOException {
    
            // $^%
            String buffer = "";
    
            try {
                // First I'm reading 3 bytes in order to have at least 3 bytes
                // in the buffer to compare them later on.
                buffer = buffer + safeRead();
                buffer = buffer + safeRead();
                buffer = buffer + safeRead();
    
                int i = 0;
                // This while will keep reading bytes and adding them to the
                // buffer until it reads $^% as the terminating sequence of bytes.
                while (!(buffer.charAt(i) == '$' && buffer.charAt(i + 1) == '^'
                        && buffer.charAt(i + 2) == '%')) {
                    buffer = buffer + safeRead();
                    i++;
                }
    
                // Returns the saved buffer after subtracting the $^% ending.
                return buffer.substring(0, buffer.length() - 3);
            } catch (IOException e) {
                /*
                 * Personally, I would remove this try/catch block and let the
                 * exception reach the caller
                 */
                e.printStackTrace();
                System.out.println(e.getMessage());
            }
    
            return buffer;
        }
    
        private char safeRead() throws IOException {
            int value = super.read();
    
            if (value == -1) {
                throw new EOFException();
            }
    
            return (char) value;
        }
    }
    

相关问题