2010-01-25 30 views
4

我有一個多線程服務器,處理客戶端請求,併爲每個連接的新線程。這非常有效,我能夠毫無問題地將「文本」消息來回發送到服務器。像聊天系統一樣。Java套接字 - 文件通過一個連接與其他數據同時傳輸

現在我想到了一種能夠通過這些客戶端連接向服務器發送文件的方式,但是我在java中看到的每個示例都始終在服務器/客戶端上有一個硬編碼的文件名 - 但我希望設置我自己的靈活性。如果它不僅能夠接收文件,而且能夠在同一個端口上模擬地接收「文本」消息,我就會喜歡它。

我有一個想法,據我目前的「文本」消息端口,告訴服務器文件將從客戶端發送,然後服務器打開一個「文件傳輸」端口,只爲文件傳輸。這樣「文本」端口可以指定文件的名稱等。另一個端口可以非常愉快地發送文件,而不會中斷。

有沒有人知道更好的方法來做到這一點,雖然?我真的不想使用兩個端口,看起來有點混亂。我寧願在服務器端創建一個單獨的線程來處理文件傳輸,並且同時處理「文本」消息,如果這甚至是可能的話?

在此先感謝,我希望我已經夠清楚:)

+0

基本上我仍然希望能夠發送消息到服務器,而文件正在傳輸:) – skyllo 2010-01-25 14:15:47

回答

4

當然,這很容易。您只需首先指定消息類型。無論是用一個字節還是用一行文本。

最簡單的方法是用這樣的一個單字節:

//to send 
Socket s = ... 
OutputStream os = s.getOutputStream(); 
if(messageIsText()){ 
    os.write(0); 
    //send text 
else{ 
    os.write(1); 
    //send file 
} 

然後在你的服務器,你可以這樣做:

Socket s = serverSocket.accept(); 
InputStream in = s.getInputStream(); 
int firstbyte = in.read(); 
if(firstbyte = 0){ 
    //read text 
} 
else{ 
    //read file 
} 

現在,這不是很flexable,但有很多事情可以做。我實際上建議你閱讀RFC 2616,這是HTTP的規範。您不需要閱讀所有內容,只需編寫簡單的Web服務器即可。這實際上很簡單(HTTP是一個非常簡單的協議,儘管它現在有很多高級功能)

如果你真的想學習網絡編程,可以嘗試編寫一個HTTP服務器。這可能聽起來令人生畏,但不用擔心,實際上並不那麼難。

0

查文件中的碎片,並沿着「正常」的線給他們。

東西鏈路:

  • 文本消息
  • 起始文件(ID < - 由客戶端發明id號,文件名)
  • 文件片(ID,與一些字節一個字節[] )
  • 端文件(ID)

服務器接收的啓動文件,並開始一個新的結構節省: *客戶端ID *發明的ID(和名稱爲什麼不! :)

未來與每個文件一塊

添加字節(也許寫入磁盤或東西)

最終文件meesage會說:好吧,沖洗和關閉!

服務器可以將文件保存在映射中,從Key對象(clientid + fileid)映射到temp結構。

+0

當然,客戶端必須有一個輔助線程讀取文件併發送塊。如果客戶端將文本消息發送到UI線程,則其他線程必須同步。無論如何,因爲它必須是同步的,所以我會使用同步方法發送所有類型的消息。 – helios 2010-01-25 14:11:51

1

聽起來像你正在重新發明的FTP。你可能想看看用Java實現的FTP服務器。 WebDAV也是如此。

0

你描述的Waht幾乎是FTP的工作原理。是的,這很麻煩,尤其是服務器打開端口的部分,因爲在防火牆和NAT的這個時代,這根本不起作用。因此,FTP必須在客戶端打開附加端口時添加「被動模式」。

但是真的沒有理由有獨立的端口。爲什麼不簡單地有一種文本消息宣佈「來了一個文件」,然後在同一端口上發送文件?

0

那麼,你有兩種選擇:帶外傳輸(就像FTP,是的,上面的人和夥計們已經說過了),或者你可以做一些交織流式傳輸。 例如,在客戶端上,您向流中發送一個類型/大小頭,然後轉儲您的文件段或文本消息(相應字節長度)。在服務器上,您可以通過每個連接線程讀取/寫入文件段,同時在某些中央消費者線程中處理文本消息(每個連接線程使用一個異步生成器)。

對於那個很酷的交錯,你可以嘗試谷歌protobuf庫 - 他們有nice primitives讀/寫小流量的數據塊,或普通/舊Object(In|Out)putStream