2012-02-13 40 views
3

我想建立一個Java應用程序作爲服務器,接受(阻止)來自Bash腳本的查詢。 Java的部分是用nio寫的,有一個主循環看起來像這樣:Bash和Java之間的通信與渠道:發送結束髮送

ServerSocketChannel ssc = ...; // bound to localhost:8011 
Charset charset = ...; 

// Waits for connections forever. 
while(true) { 
    SocketChannel sc = ssc.accept(); 
    StringBuffer sb = new StringBuffer(); 
    int read = 0; 
    // Builds up a string representing the query. 
    while(true) { 
    ByteBuffer bb = ByteBuffer.allocate(1024); 
    read = sc.read(bb); 
    if(read == -1) break; 
    bb.flip(); 
    CharBuffer cb = charset.decode(bb); 
    sb.append(cb.toString()); 
    } 
    // Do something with the query. 
    sc.write(charset.encode(CharBuffer.wrap(sb.toString()))); 
    sc.close(); 
} 

Bash的部分依賴於/dev/tcp/法寶:

exec 3<> /dev/tcp/localhost/8011 
echo "message" 1>&3 

我可以看到該消息從猛砸發送確實到達Java部分(如果我在內部循環中添加一個System.out.println(cb);,我可以看到這些部分),但內部循環不會終止,除非我終止Bash腳本。

我的問題其實很簡單:Bash腳本如何向Java服務器發出通信已結束的信號?我試過添加

echo -en "\004" 1>&3 

在我的Bash腳本中,但沒有幫助。

+0

再次想到,我可能會誤解渠道是如何運作的。我試圖達到的目的是讓Java認爲溝通已經結束,但可能會在稍後恢復。不知何故,我認爲這應該是一個不同於簡單關閉頻道的行爲,但這可能是錯誤的。也許我真正需要的是一個小小的協議,它說「這就是消息的結尾」。爲我澄清這一點的答案也是可以接受的。 – Philippe 2012-02-13 18:59:48

回答

1

嘗試關閉文件描述符。這應該被Java視爲封閉流,並允許內部循環終止。

exec 3>&- 

套接字可能是「半開」(即關閉一個方向但仍然打開另一個)。 A Socket實例有methods to detect這個狀態。

我還沒有測試bash創建的管道插座混合是否支持這個。如果沒有,你將不得不設計一個帶有一些內部長度編碼或分隔序列的協議來指示消息邊界。

+0

感謝您的語法。問題是Java不能寫入通道(即服務器不能「用查詢做某事」)。 – Philippe 2012-02-13 19:19:37

+0

@Philippe你嘗試過嗎?我沒有對它進行測試,但是插座可能是「半開」(即關閉一個方向但仍然打開)。如果這不起作用,那麼你真的需要問一個不同的問題(關於協議設計),因爲你發佈的協議似乎取決於關閉輸入,但保持輸出打開。 – erickson 2012-02-13 19:26:17

+0

是的,我嘗試過; Java端拋出一個IOException「Broken pipe」。我也開始認爲我的問題是錯誤的,因爲我最初誤解了'-1'的返回代碼對於'read'的含義(請參閱我自己的問題)。 – Philippe 2012-02-13 19:47:06

1

我想要實現的是讓Java認爲 通信已經結束,但可能稍後恢復。

你需要明白這個要求是矛盾的。通訊已結束它可能會稍後恢復。 TCP中沒有任何東西支持這一點,在Java中也沒有任何東西。