2012-05-10 27 views
2

我越來越沮喪在java.net.SocketOutputStream,只是拒絕正確刷新!我必須忽視這個明顯的問題。在我下面的Groovy腳本中,我嘗試連接到在Galaxy Nexus Android 4.0.2手機上運行的簡單套接字服務器,並在我的5秒超時過期後立即給出套接字關閉異常。無法刷新Groovy套接字

SocketClient.groovy

import java.net.* 
socket = new Socket() 
socket.connect(new InetSocketAddress(InetAddress.getByAddress([172,17,57,21] as byte[]), 58789), 5000) 
println "Connected!" 
socket.withStreams { input, output -> 
    println "Processing ${input.class.name} and ${output.class.name} streams..." 
    output.withWriter { 
     it << 'echo testing\n\n'; 
     it.flush(); 
     output.flush() 
     def readerThread = Thread.start { 
      println "Request written, reading response..."; println input.text 
     } 
     println "Waiting 5 secs for read to complete." 
     readerThread.join(5000) 
    } 
    println "Stream closed!" 
} 

我試過沖洗所有不同的手段,包括輸出流間接包裝與作家和沖洗的直接沖洗。在數據流關閉之前服務器上沒有數據出現,導致套接字關閉,導致套接字讀取嘗試失敗。我究竟做錯了什麼?我也會在下面嵌入我的Android代碼。這是一個啓動套接字服務器的簡單活動。

MyServer.java

package com.example; 

import android.app.Activity; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.TextView; 

public class MyServer extends Activity 
{ 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     RawSocketServer rawSocketServer = new RawSocketServer(); 
     String port = rawSocketServer.getLocalPort(); 
     TextView textView = (TextView) this.findViewById(R.id.mainTextView); 
     textView.setText("Server bound to port " + port); 
     rawSocketServer.start(); 
    } 
} 

RawSocketServer.java

package com.example; 

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.PrintWriter; 
import java.net.ServerSocket; 
import java.net.Socket; 

/** 
* Created by IntelliJ IDEA. 
* User: cliff 
* Date: 5/9/12 
* Time: 4:03 PM 
*/ 
public class RawSocketServer { 

    public static final int PORT = 0; 
    private ServerSocket serverSocket; 

    public RawSocketServer() { 
     this(PORT); 
    } 

    public RawSocketServer(int port) { 
     try { 
      this.serverSocket = new ServerSocket(port); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      throw new RuntimeException("server cannot bind to port " + port); 
     } 
    } 

    public void start() { 
     new Thread(new Runnable() { 
      public void run() { 
       go(); 
      } 
     }).start(); 
    } 

    private void go() { 
     Socket socket = null; 
     while (true) { 
      try { 
       socket = this.serverSocket.accept(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
       throw new RuntimeException("cannot accept from server socket" + e); 
      } 
      BufferedReader reader = null; 
      try { 
       reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
      } catch (IOException e) { 
       e.printStackTrace(); 
       throw new RuntimeException("Could not get input stream from socket. " + e); 
      } 
      PrintWriter writer = null; 
      try { 
       writer = new PrintWriter(socket.getOutputStream()); 
      } catch (IOException e) { 
       e.printStackTrace(); 
       throw new RuntimeException("Could not get output stream from socket. " + e); 
      } 
      try { 
       for (String line = reader.readLine(); line !=null; line = reader.readLine()) { 
        writer.print(line); 
       } 
      } catch (IOException e) { 
       e.printStackTrace(); 
       throw new RuntimeException("Error reading/writing from/to socket. " + e); 
      } 
     } 
    } 

    public String getLocalPort() { 
     return "" + serverSocket.getLocalPort(); 
    } 
} 

回答

1

我想知道....你有 「它< < '迴響測試'」 有。在Writer上使用它意味着不寫行結束。由於您的服務器使用readLine,因此需要一行結束。因此數據可能會到達,但readLine並未完成,因爲它等待行結束。然後,修復程序就會執行例如「它< <'回聲測試\ n'」或「它< <'回聲測試'< <'\ n'」。

現在我不太瞭解Android API,但是您的服務器在「writer.print(line);」中可能有相同的問題,因爲我認爲使用readLine讀取的一行不包含該行結束了。但由於這不再讀,現在應該沒有問題。

+0

嘿blackdrag,趕上!這是完全合理的,我會檢查一下! – Cliff

+0

昨晚我又試了一次,並添加了新的代碼到我的Groovy套接字客戶端,但我仍然得到相同的行爲。我剛剛發現你提到的服務器可能有同樣的問題,所以我會嘗試下一步。 – Cliff

1

我終於明白了這一點與Blackdrag的幫助。我的問題是在多個領域。客戶端讀取會因爲缺少新行而掛起(如blackdrag建議)。此外,服務器讀取循環會掛起,因爲客戶端永遠不會關閉其寫入流。這會導致雞和蛋的問題,關閉寫入流會關閉關閉讀取流的套接字。如果你願意的話,我最終需要添加一個「協議」,這將指示對話何時完成,服務器應該停止讀取並關閉套接字。在客戶端寫入「完成」字符串就成了該指標。下面是工作客戶端和服務器的完整源代碼:(我知道這是非常糟糕的Android代碼,但它最初只是爲了測試我的新Galaxy Nexus上的通信,我仍然在學習如何使用iOS空間!)

SocketClient.groovy

import java.net.* 
socket = new Socket() 
socket.connect(new InetSocketAddress(InetAddress.getByAddress([172,17,57,21] as byte[]), 58302), 5000) 
println "Connected!" 
socket.withStreams { input, output -> 
    println "Processing ${input.class.name} and ${output.class.name} streams..." 
    output.withWriter { 
     it << 'my name is cliff\ndone\n'; 
     it.flush(); 
     output.flush() 
     def readerThread = Thread.start { 
      println "Request written, reading response..."; println input.text 
     } 
     println "Waiting 5 secs for read to complete." 
     readerThread.join(60000) 
    } 
    println "Stream closed!" 
} 

MyServer.java

package com.example; 

import android.app.Activity; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.TextView; 

public class MyServer extends Activity 
{ 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     RawSocketServer rawSocketServer = new RawSocketServer(); 
     String port = rawSocketServer.getLocalPort(); 
     TextView textView = (TextView) this.findViewById(R.id.mainTextView); 
     textView.setText("Server bound to port " + port); 
     rawSocketServer.start(); 
    } 
} 

RawSocketServer.java

package com.example; 

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.PrintWriter; 
import java.net.ServerSocket; 
import java.net.Socket; 

/** 
* Created by IntelliJ IDEA. 
* User: cliff 
* Date: 5/9/12 
* Time: 4:03 PM 
*/ 
public class RawSocketServer { 

    public static final int PORT = 0; 
    private ServerSocket serverSocket; 

    public RawSocketServer() { 
     this(PORT); 
    } 

    public RawSocketServer(int port) { 
     try { 
      this.serverSocket = new ServerSocket(port); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      throw new RuntimeException("server cannot bind to port " + port); 
     } 
    } 

    public void start() { 
     new Thread(new Runnable() { 
      public void run() { 
       go(); 
      } 
     }).start(); 
    } 

    private void go() { 
     Socket socket = null; 
     while (true) { 
      try { 
       socket = this.serverSocket.accept(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
       throw new RuntimeException("cannot accept from server socket" + e); 
      } 
      BufferedReader reader = null; 
      try { 
       reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
      } catch (IOException e) { 
       e.printStackTrace(); 
       throw new RuntimeException("Could not get input stream from socket. " + e); 
      } 
      PrintWriter writer = null; 
      try { 
       writer = new PrintWriter(socket.getOutputStream()); 
      } catch (IOException e) { 
       e.printStackTrace(); 
       throw new RuntimeException("Could not get output stream from socket. " + e); 
      } 
      try { 
       for (String line = reader.readLine(); line !=null; line = reader.readLine()) { 
        if(line.trim().equalsIgnoreCase("done")) break; 
        writer.println(line); 
        writer.flush(); 
       } 
       writer.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
       throw new RuntimeException("Error reading/writing from/to socket. " + e); 
      } 
     } 
    } 

    public String getLocalPort() { 
     return "" + serverSocket.getLocalPort(); 
    } 
} 
+0

很高興看到你解決了你的問題 – blackdrag

+0

Thanx的幫助! – Cliff