[英]Java socket: Pushing requests to client through socket
我當前正在制作一個客戶端-服務器應用程序,該應用程序主要用於對服務器進行過程調用並等待數據包響應。
但是,我想讓服務器(自發地)向客戶端“推送”新聞,但是如果客戶端偵聽另一個數據包響應時消息到達,這似乎是一個問題。
是否可以通過同一套接字實例將套接字拆分為2個唯一的通道流? 還是使一個客戶端線程僅偵聽傳入的連接並將其分派到隊列中會更好?
使用雙向客戶端-服務器連接時,有哪些常見的模式和做法? (自發出現的地方)
為了提醒我,我使用Java Socket,ObjectInputStream和ObjectOutputstream。 我沒有使用Java RMI。
因此,在學習網絡時會遇到的一件事就是失去同步。 例如,當您“硬編碼”一組特定的客戶端-服務器交互時,就會發生這種情況。
server sends 2 byte status code
client receives 2 byte status code
client responds with 4 byte operation code
如果由於某種原因存在一個錯誤,導致該交互的任何部分均未按需要准確發生,則該程序的其余部分將失敗,因為現在所有網絡交互都不同步。 當服務器確實發送int時,客戶端可能會讀取它認為代表字符串的一組字節,依此類推。 最糟糕的是,您可能會發現主網絡線程陷入僵局,因為客戶端和服務器都在同時等待輸入。
在一個較大的項目中,肯定有很多錯誤,如果您使用這種風格進行編碼, 則會發生很多事情。 因此,我們有一個叫做Middleware的東西。
TLV消息協議是一種非常常見且靈活的中間件范例。 您將實現一些簡單的類(使用准Java偽代碼);
TLVMessage
int type;
byte[] value;
TLVPusher implements Runnable
OutputStream out;
Queue<TLVMessage> messages;
run() {
while(true) {
//poll and write front of queue to out (INCLUDING value.length!)
}
}
TLVReader implements Runnable
InputStream in;
Queue<TLVMessage> messages;
run() {
while(true) {
//read message from in and add to queue
}
}
現在,您在客戶端上運行了兩個線程,在服務器上運行了兩個線程。 每個端都有自己的Pusher
和Reader
。 需要注意的重要一點是,因為您將length字段寫入輸出流,所以讀取器始終知道需要讀取多少字節。 因此,即使一個消息被錯誤地序列化了,它的長度仍然是正確的,並且下一條消息將始終從第一個字節到最后一個字節被正確讀取。 這樣,您的程序就永遠不會失去同步。
您只需將TLVMessage
對象添加到pusher.queue
,它們將到達套接字另一端的reader.queue
。 然后,您可以按消息的type
字段處理消息(在另一個reader.messages.size()
線程中)。
您無需擔心事情發生的順序,您有一個健壯的機制可以在兩個方向上在客戶端和服務器之間傳遞消息。 您已經抽象了一些雜亂無章的網絡內容,並且可以繼續進行編碼。
當然,有圖書館為您完成所有這些工作,但是我認為始終值得了解如何以及為什么這樣做。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.