背景:
今天没事自己模拟 socket 请求时发现了一个问题:
- // 测试代码
- public static void http(String path) throws Exception {
- URL url = new URL(path);
- final String host = url.getHost();
- // 如果指明了端口, 则拿到端口, 否则是 - 1
- int port = url.getPort();
- int defaultPort = url.getDefaultPort();
- final String file = url.getFile();
- Socket socket = new Socket(host, port == -1 ? defaultPort : port);
- InputStream is = socket.getInputStream();
- final BufferedReader br = new BufferedReader(new InputStreamReader(is));
- final OutputStream os = socket.getOutputStream();
- // 开启一个线程用来读取数据
- new Thread(){
- @Override
- public void run() {
- String line;
- try {
- while ((line = br.readLine()) != null){
- Log.e("TAG",line);
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }.start();
- // 开启一个线程用来发送数据
- new Thread(){
- @Override
- public void run() {
- SystemClock.sleep(10000);
- try {
- // 请求行
- os.write(("GET"+file+"HTTP/1.1\r\n").getBytes());
- os.write(("Host:"+host+"\r\n").getBytes());
- os.write(("\r\n").getBytes());
- os.flush();
- }catch (Exception e){ }
- }
- }.start();
- /*// 请求行
- os.write(("GET"+file+"HTTP/1.1\r\n").getBytes());
- os.write(("Host:"+host+"\r\n").getBytes());
- os.write(("\r\n").getBytes());
- os.flush();*/
- }
通过代码都能看到:
我用了两种测试方式:
第一次: 开启一个线程用来读取数据, 发送数据没有在子线程中发送, 但是是在读取数据方法的下面. 按照常理来说这样的代码会先执行读取数据的方法. 结果通过断点调试发现是先执行的发送数据的方法, 然后执行的读取数据的方法. 这里可能就会有人说了开启线程需要少量的时间. 好, 那么我就有了第二次测试.
第二次 (如上面代码): 我把发送数据的代码也在 z 线程中执行, 并且在该线程中睡 10 秒之后在执行发送数据的代码, 结果还是和上面一样: 先执行的发送数据的代码, 然后再执行的读数据的方法.
针对上面问题其实有一个误解, 就是对 readLine() 方法的误解. 误以为 readLine() 是读取到没有数据时就返回 null. 而实际上 readLine() 是一个阻塞函数. 当没有数据读取时, 就会造成 IO 阻塞, 这个方法就会一直阻塞在这里. 所以只有等发送数据的方法执行完之后, readLine() 才会读取到数据, 接着下面的才会正常执行.
来源: http://www.jianshu.com/p/cdb2def6bb90