回答
這取決於很多事情。如果你想有一個真正的答案,你應該清楚地瞭解到你的程序將做和你的
如果生產率的快速您的有效定義範圍,我所使用的方法「高效」的定義下什麼下降在過去涉及序列化將簡單的舊java對象向下發送到套接字。最近我發現,結合netty API,我能夠快速建立相當強大的客戶端/服務器通信原型。
膽量相當簡單;客戶端和服務器都使用管道中的ObjectDecoder和ObjectEncoder運行Netty。每個爲處理數據而設計的對象都有一個類。例如,一個HandshakeRequest類和HandshakeResponse類。
握手請求可能看起來像:
public class HandshakeRequest extends Message {
private static final long serialVersionUID = 1L;
}
和握手響應可能看起來像:
public class HandshakeResponse extends Message {
private static final long serialVersionUID = 1L;
private final HandshakeResult handshakeResult;
public HandshakeResponse(HandshakeResult handshakeResult) {
this.handshakeResult = handshakeResult;
}
public HandshakeResult getHandshakeResult() {
return handshakeResult;
}
}
在網狀
,當客戶端連接這樣的服務器會發送一個握手請求:
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
Channel ch = e.getChannel();
ch.write(new HandshakeRequest();
}
客戶端收到HandshakeRequest對象,但它需要一個告訴服務器剛剛發送了什麼樣的消息。爲此,可以使用Map<Class<?>, Method>
。當你的程序運行時,它應該通過具有反射的類的方法進行迭代並將它們放置在地圖中。這裏是一個例子:
public HashMap<Class<?>, Method> populateMessageHandler() {
HashMap<Class<?>, Method> temp = new HashMap<Class<?>, Method>();
for (Method method : getClass().getMethods()) {
if (method.getAnnotation(MessageHandler.class) != null) {
Class<?>[] methodParameters = method.getParameterTypes();
temp.put(methodParameters[1], method);
}
}
return temp;
}
這個代碼將遍歷當前類和尋找標有註解@MessageHandler方法,然後看看該方法的第一個參數(該參數是一個對象,如public void handleHandshakeRequest(HandshakeRequest request)
)並將該類作爲關鍵字與實際方法放在地圖中,因爲它是值。
與此映射的地方,這是很容易獲得的消息,該消息直接發送到應處理消息的方法:
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
try {
Message message = (Message) e.getMessage();
Method method = messageHandlers.get(message.getClass());
if (method == null) {
System.out.println("No handler for message!");
} else {
method.invoke(this, ctx, message);
}
} catch(Exception exception) {
exception.printStackTrace();
}
}
有沒有真的沒有什麼東西留下來了。 netty處理所有雜亂的東西,允許我們輕鬆地來回發送序列化的對象。如果您決定不想使用netty,則可以將自己的協議包裝在java的Object Output Stream中。你將不得不整體做更多的工作,但溝通的簡單性保持不變。
這是一個有點很難說哪一種方法是在什麼樣的條件「最高效」,我不知道你的用例,但這裏有幾個選項:
最基本的方法是簡單地使用「原始」TCP套接字。好處是沒有什麼額外的網絡移動,你自己創建你的協議,後者也是一個缺點;您必須設計和實現您自己的通信協議,以及處理服務器端多個連接的基本框架(如果需要的話)。使用UDP套接字,你可能會節省一點延遲和帶寬(並不是很多,除非你使用類似移動數據的東西,你可能不會注意到TCP在延遲方面有任何不同),但網絡代碼有點難度; UDP套接字是「無連接的」,這意味着所有的客戶端消息將在同一個處理程序中結束,並且必須相互區分。如果服務器需要跟上客戶端狀態,那麼執行權利可能會有些麻煩。
MadProgrammer帶來了RMI(遠程方法調用),我個人從來沒有使用它,它似乎有點麻煩設置,但從長遠來看可能是相當不錯的實施方面。
也許最常見的一種方法是使用http進行通信,例如通過REST-interface來代替Web services。有多種框架(我個人比較喜歡Spring MVC)來幫助實現,但是現在學習一個新的框架可能已經超出了你的範圍。此外,複雜的http查詢或長時間的URL可能會讓你的帶寬多一點,但除非我們談論的是大量同時發生的客戶端,否則這通常不成問題(假設您將服務器運行在數據中心與100/100MBit連接等)。如果有的話,這可能是最容易擴展的解決方案,因爲有很多可用於Web服務器的負載平衡解決方案。
- 1. adobe air桌面應用程序 - 與服務器不斷通信
- 2. 服務與網絡/桌面應用程序之間的通信
- 3. 允許服務與桌面交互 - Windows服務與OPC服務器通信
- 4. 與桌面應用程序通信
- 5. JavaFX小程序與服務器通信
- 6. 與c#程序通信erlang服務器
- 7. Windows服務和桌面應用程序之間的通信
- 8. 通過遠程桌面服務器贏得安裝程序2003
- 9. 桌面應用程序如何與Web應用程序通信?
- 10. Silverlight與桌面進程的通信
- 11. 通過桌面應用程序加載測試Web服務器
- 12. Windows應用程序或服務與遠程桌面上的其他服務通信
- 13. 與Windows 2003服務器相比,Winforms程序通過Windows 2012服務器上的遠程桌面更大
- 14. Android與服務器通信
- 15. 與http服務器通信
- 16. 桌面客戶端Web服務器通信
- 17. Winforms應用程序服務器通信
- 18. WIndows服務在遠程桌面運行桌面程序
- 19. iOS應用程序通常如何與服務器通信?
- 20. Android應用程序通過插座與服務器通信
- 21. Linux Ubuntu桌面與服務器
- 22. 遠程桌面服務器應用
- 23. Android:如何與Windows桌面應用程序進行通信?
- 24. 與桌面應用程序通信,調用DLL函數
- 25. 服務器,JavaFX桌面應用程序和Android應用程序之間的通信
- 26. 通過c與socket.io服務器通信#
- 27. 客戶端與服務器之間的小程序通信
- 28. android應用程序和與星號服務器通信
- 29. java 2客戶端應用程序與服務器通信
- 30. 將與服務器通信的應用程序 - 科爾多瓦?
「最高效」的條款是什麼?帶寬,CPU時間,延遲,內存?或者只是最容易實現? – esaj
我對[RMI](http://docs.oracle.com/javase/tutorial/rmi/index.html)的投票,本質上,通過網絡Objets – MadProgrammer
延遲,我不希望用戶等待響應時間到每一個行動。 – Eleeist