简体   繁体   English

从Socket读取

[英]Reading from Socket

I am having issues getting this simple class to work. 我有问题让这个简单的类工作。 It basically connects to an IMAP server and reads the banner. 它基本上连接到IMAP服务器并读取横幅。 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. 在调试器中,我可以逐步执行while循环,看到正在读取所有字符,最终它将从循环中退出。 But the last System.out.println statement is never reached. 但是永远不会到达最后一个System.out.println语句。

import java.io.BufferedReader;
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. 如果没有要读取的数据,则读取功能块,仅在readStream关闭或套接字连接断开时才会出现。 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.. 还有一件事,因为read()阻塞,等待更多数据,建议你应该在后台线程中读取..

ok this is what I did to solve my particular problem. 好的,这就是我为解决我的特殊问题所做的。 Note, using ready() or available() method is not always reliable. 注意,使用ready()或available()方法并不总是可靠的。 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));
    }

}

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

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