2012-01-22 91 views
2

我有一個Java程序,我在家用服務器上運行。我還有一個java客戶端程序,它將消息發送到服務器並使用套接字接收響應。Java套接字通信 - 提高速度

我已經成功實現了它,但它似乎有點慢,我試圖儘可能快地實現它。

這裏是我的代碼:

服務器

public class Server implements Runnable{ 
    static ServerSocket socket1; 
    protected final static int port = 4701; 
    static Socket connection; 
    static StringBuffer process; 

private String handleRequest(String req){ 
    if(req.equals("marco")){ 
     return "polo"; 
    }else 
     return "null"; 

} 

public void run(){ 
    try { 
     socket1 = new ServerSocket(port); 
     int character; 

     while (true) { 
      connection = socket1.accept(); 

      BufferedInputStream is = new BufferedInputStream(connection.getInputStream()); 
      InputStreamReader isr = new InputStreamReader(is); 
      process = new StringBuffer(); 
      while ((character = isr.read()) != 13) { 
       process.append((char) character); 
      } 
      String returnCode = handleRequest(process.toString()) + (char) 13; 
      BufferedOutputStream os = new BufferedOutputStream(connection.getOutputStream()); 
      OutputStreamWriter osw = new OutputStreamWriter(os, "US-ASCII"); 
      osw.write(returnCode); 
      osw.flush(); 
     } 
    } catch (IOException e) { 
     System.out.println("error starting server " + e.getMessage()); 
    } 
    try { 
     if(connection != null) 
      connection.close(); 

    } catch (IOException e) { 
    } 

客戶

String host = "xx.xx.xx.xxx"; 
    int port = 4701; 

    StringBuffer instr = new StringBuffer(); 

    try { 
     InetAddress address = InetAddress.getByName(host); 

     Socket connection = new Socket(address, port); 

     BufferedOutputStream bos = new BufferedOutputStream(connection. 
       getOutputStream()); 

      OutputStreamWriter osw = new OutputStreamWriter(bos, "US-ASCII"); 

      String process = "marco" + (char) 13; 

      osw.write(process); 
      osw.flush(); 

      BufferedInputStream bis = new BufferedInputStream(connection. 
       getInputStream()); 

      InputStreamReader isr = new InputStreamReader(bis, "US-ASCII"); 

      int c; 
      while ((c = isr.read()) != 13) 
       instr.append((char) c); 

      connection.close(); 
      } 
      catch (Exception e){} 

      if(instr.toString().equals("")){ 
       //error 
      } 


} 

因此,例如,我將各種字符串發送給服務器,以確定如何在服務器會迴應。例如,如代碼所示,如​​果我將「marco」發送到服務器,我會返回「polo」。我還有(char) 13作爲分隔符讓程序知道消息已結束。

有沒有人有關於如何降低轉移時間的一些想法?我讀過關於禁用nagle算法等事情。這會有幫助嗎?如果我想純粹的速度,也許套接字不是要走的路。也許不同的語言或圖書館會更快?

+0

是什麼讓你覺得它「有點慢」? – Mat

+0

更多的情況下,我需要儘可能快:) –

+3

是的,這是我的觀點:你怎麼知道它不是? – Mat

回答

4

在服務器端,你需要關閉連接。否則,它們會保持打開狀態,直到將來某些垃圾收集時間爲止。

如果你真的渴望低延遲,那麼使用DatagramSocket(即UDP而不是TCP)。您丟失了消息傳遞保證,並且必須期望丟失數據包,但對於良好網絡中的短消息,延遲與可移植代碼的延遲一樣好。

另一種選擇是重複使用客戶端的套接字連接,而不是每次重新打開它。對於像你這樣的微小消息,大部分時間可能在TCP設置和拆卸中消耗。

微優化將停止使用逐字符處理,並將字符串作爲字符串匹配您的「marco」和「polo」。但這不太可能會顯着改善。

+0

偉大的建議謝謝。當你提到保持連接打開時,這意味着什麼?我想我對連接打開和關閉時實際發生的事情有點困惑。是否有通過開放連接發送的持續數據流?在發送「marco」消息之前,服務器和客戶端之間是否有通信?即他們是否對第一次互相打招呼 –

+1

我的意思是:在你的例子中,客戶端打開套接字,發送消息,等待回覆並關閉連接。在一些更現實的情況下,發送/接收邏輯周圍可能會有一個while循環。在這種情況下,您會希望在每次循環迭代中重複使用相同的TCP連接而不是打開/關閉。在更復雜的情況下,您不知道何時/是否要進行其他連接,那麼您可以使用具有到期空閒連接的池。在這種情況下,請考慮http://commons.apache.org/pool/ –

1

有很多事情你可以採取不同的方式使其更快,但它清楚你必須改變。通常最長的延遲是在你的網絡中。

如果您通過環回或低延遲網絡連接,則可以使用NIO,並且速度可能更快。但是,如果您使用的是常規網絡,尤其是在使用互聯網連接的情況下,程序的效率並沒有太大的差別。

當您考察性能時,您需要查看整個端到端解決方案,並查看延遲時間,並將注意力放在最大限度地減緩解決方案的事情上。

0

套接字是相當低級的,所以我懷疑有更快的Java庫很容易使用。 Java可能不是最快的語言,並且最流行的服務器通常用C/C++編寫。但是,在Java服務器上運行的許多大型項目,TomcatResinJBoss等等。

說到優化,通常的做法是讓服務器多線程。在ServerSocket.accept()之後,您創建了一個處理請求的新線程,以便服務器可以回來爲其他客戶端提供服務。

這裏是一個很好的文章,顯示的多線程響應套接字請求

http://www.oracle.com/technetwork/java/socket-140484.html

+0

感謝您的回答。事實上,我需要服務的客戶端數量只有1個,但這是一個有趣的讀取 –