开发者

Reading from Socket

开发者 https://www.devze.com 2023-03-28 17:55 出处:网络
I am having issues getting this simple class to work. It basically connects to an IMAP server and reads the banner. But after reading all chars, it is somewhat hanging. In the debugger I can step thro

I am having issues getting this simple class to work. It basically connects to an IMAP server and reads the banner. But after reading all chars, it is somewhat hanging. In the debugger I can step through the while loop and see all chars are being read and eventually it is coming out of the loop. But the last System.out.println statement is never reached.

import java.io.BufferedR开发者_高级运维eader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.Socket;


public class TestClient
{

    /**

        @param args

     */
    public static void main( String[] args ) throws Exception
    {

        Socket socket = new Socket( "imap.1and1.com", 143 );

        DataOutputStream os = new DataOutputStream( socket.getOutputStream() );
        BufferedReader reader = new BufferedReader( new InputStreamReader( socket.getInputStream() ) );

        StringBuilder sb = new StringBuilder();
        char ch = (char) reader.read();
        while ( ch != -1 ) {
            sb.append( ch );
            ch = (char) reader.read();

        }

        System.out.println( sb.toString() ); /// <--- never prints anything and program just hangs..
    }

}


read function blocks if there is no data to read, only comes out when readStream is closed or socket connection got disconnected. What you should do is to create a protocol which disconnect the connection after data has been read fully. ie you should come out of the loop

  • either by somehow disconnecting the connection after all data has been read (for that you must identify all data has been read)

  • or get out of the loop yourself if you have read some previously agreed "end of message" string..

One more thing, since read() blocks, waiting for more data, it is advised you should read in a background thread..


ok this is what I did to solve my particular problem. Note, using ready() or available() method is not always reliable. Especially if the server is expected to send data, pause and then send more data. In my case it works because I am not expecting server to stop in the middle of a response and restart again.

The code is obviously not optimized for real use.

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.Socket;

/**
        @author Mir Shafiqul Islam &lt;mislam@mirislam.comt&gt;

 */
public class TestClient
{

    /**

        @param args

     */
    public static void main( String[] args ) throws Exception
    {
        // Open the socket
        Socket socket = new Socket( "localhost", 25143 );
        // Get a buffered reader
        BufferedReader reader = new BufferedReader( new InputStreamReader( socket.getInputStream() ) );
        // At this point it is too early to read. So it most likely return false
        System.out.println( "Buffer Reader ready? " + reader.ready()); 
        // StringBuilder to hold the response
        StringBuilder sb = new StringBuilder();
        // Indicator to show if we have started to receive data or not
        boolean dataStreamStarted = false;
        // How many times we went to sleep waiting for data
        int sleepCounter = 0;
        // How many times (max) we will sleep before bailing out
        int sleepMaxCounter = 50;
        // Sleep max counter after data started
        int sleepMaxDataCounter = 3;
        // How long to sleep for each cycle
        int sleepTime = 50;
        // Start time
        long startTime = System.currentTimeMillis();
        // This is a tight loop. Not sure what it will do to CPU
        while( true ) {
            if ( reader.ready() )
            {
                sb.append( (char) reader.read() );
                // Once started we do not expect server to stop in the middle and restart
                dataStreamStarted = true; 
            } else {
                Thread.sleep( sleepTime );
                if ( dataStreamStarted && (sleepCounter >= sleepMaxDataCounter) ) {
                    System.out.println( "Reached max sleep time of " + (sleepMaxDataCounter*sleepTime) + " ms after data started" );
                    break;
                } else {
                    if (sleepCounter >= sleepMaxCounter) {
                        System.out.println( "Reached max sleep time of " + (sleepMaxCounter*sleepTime) + " ms. Bailing out" );
                        // Reached max timeout waiting for data. Bail..
                        break;
                    }
                }
                sleepCounter++;
            }

        }
        long endTime = System.currentTimeMillis();

        System.out.println( sb.toString() );
        System.out.println( "Time " + (endTime-startTime));
    }

}
0

精彩评论

暂无评论...
验证码 换一张
取 消