我正在嘗試設定一個程式,服務器可以在其中與多個客戶端進行通信。該程式是用Java撰寫的。我在同一臺機器上完成了所有作業,所以我決定嘗試 LAN。我將程式轉換為 JAR 檔案,并嘗試將我的筆記本電腦連接到我的 PC(兩者都在同一網路上)。連接成功,但不幸的是只有 1 條訊息到達服務器。正如你可以在下面的代碼中看到,我送多個訊息(意思就是我寫多次)通過DataOutputStream。一個定義資料型別(在下面的示例中,0 表示它是一個字串),另一個發送實際的訊息資料。我還以位元組為單位列印資料包的大小,它始終與DataOutputStream實體的大小匹配。
DataOutputStream dOut = new DataOutputStream(clientSocket.getOutputStream());
String str = "Hello";
//Type
System.out.println("Type output size: 1");
dOut.writeByte(0);
//Message
System.out.println("Message output size: " (str.getBytes(StandardCharsets.UTF_8).length 2));
dOut.writeUTF(str);
System.out.println("Length of all: " (dOut.size()));
dOut.flush();
所以現在當來自客戶端的資料被發送時,我們需要在服務器上處理它,下面的代碼就是這樣做的。它InputStream從被Socket呼叫的客戶端檢索并將其插入到DataInputStream. 這是因為它在 LAN 上變得很奇怪,因為流只包含第一條訊息。
InputStream stream = client.getInputStream();
DataInputStream dIn = new DataInputStream(stream);
while(dIn.available() > 0) {
byte type = dIn.readByte();
switch(type) {
case 0:
System.out.println(dIn.readUTF());
break;
case 1:
System.out.println(dIn.readInt());
break;
case 2:
System.out.println(dIn.readByte());
break;
default:
throw new IllegalStateException("Unexpected value: " type);
}
}
如果您在 IDE 中運行客戶端,比如連接到同一網路的筆記本電腦,然后您在連接到同一網路的 PC 上運行服務器,它將作業。但是,如果程式在 JARS 中,則不會。
實際的堆疊跟蹤如下:
java.net.SocketException:連接重置在 java.base/sun.nio.ch.NioSocketImpl.implRead(NioSocketImpl.java:323) 在 java.base/sun.nio.ch.NioSocketImpl.read(NioSocketImpl.java:350)在 java.base/sun.nio.ch.NioSocketImpl$1.read(NioSocketImpl.java:803) 在 java.base/java.net.Socket$SocketInputStream.read(Socket.java:966) 在 java.base/java。 net.Socket$SocketInputStream.read(Socket.java:961) 在 java.base/java.io.DataInputStream.readInt(DataInputStream.java:393)
堆疊跟蹤并沒有告訴我任何東西,但它在指向case 0:的switch case。它無法讀取字串,因為DataInputStream它不包含任何資料(我猜?)。
我還要宣告服務器是多執行緒的!我有一個執行緒在套接字被接受時添加套接字ServerSocket.accept(),我使用第二個(主執行緒)讀取從客戶端發送的資料。
我選擇了上面的代碼,因為我相信問題出在其中,但是我是 Socket Programming 的新手,我知道你們中的一些人希望看到代碼的其他部分。當我被問到時,我會添加更多相關代碼。
我不知道為什么它會這樣,有誰知道為什么?
我試過什么?
- 我試過等待資料包 - 但這只會導致服務器永遠回圈。等待資料包我的意思是在
DataInputStream包含足夠的位元組之前不會前進。 - 我已經
Nagels Algorithm通過setTCPNoDelay(false). - 嘗試發送不同的資料型別,但也失敗了
- I tried changing the first packet to a
Stringwhich resulted in theStringshowing up in theDataInputStream. - I have tried portforwarding the port used and I have tried disabling the firewall on both computers.
Update 1
I have been taking advice from the comments which has led a to a few discoveries:
- Closing the
DataOutputStreamsuccessfully sends all packets to the client. - It is also possible to build your own buffer and decode it in the server. However, it is still not possible to send any more messages after this.
- It worked as a JAR because IntelliJ was being nice (Eclipse threw the same error when running in IDE)
Update 2: I think this post is relevant. It states that SocketException is sent when a client closes it's socket "ungracefully". And because my Client closes (as it is not in a loop) and I don't close the socket properly - it will close "ungracefully" and the data will be lost. Hence the error.
uj5u.com熱心網友回復:
現在問題已經解決了,解決方案也很合乎邏輯。我的客戶端不是回圈操作,而是發送資料并關閉程式。這聽起來不錯,但我忘了正確關閉客戶端的套接字。
第二個“資料包”從未到達的原因是我犯了這個小錯誤。資料包正在通過本地網路,但客戶端套接字在資料包到達服務器之前不正確地關閉了它的套接字,這就是我收到 SocketException 錯誤的原因。看到這個。
在發送了我想發送的所有訊息后,我通過放置客戶端的套接字socket.close()在哪里解決了這個問題socket。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/371394.html
標籤:java multithreading sockets tcp
