我有一個android設備和一個服務器。服務器可以傳輸一條消息,告訴設備從wifi上斷開連接。要快速知道這是怎麼做的話,這裏有一個psudo序列圖:在緩衝讀取器中缺少第一個字符
現在,有趣的是,當客戶端重新連接,服務器發送一個消息,有時該消息丟失第一字符,有時它是下一個消息。無論如何,在客戶端重新連接之後它發生的很快。
而且例如環這裏示出,從服務器側看出:
while (true) {
server_.transmitMessage("SLAVE", "WIFI");
Thread.sleep(40000);
System.out.println("Should be back");
server_.transmitMessage("SLAVE", "Hi wififims");
Thread.sleep(5000);
}
而從Android裝置的輸出:
03-05 15:36:01.200 17152-17180/com.example.bla.psedowifidims I/System.out: Conecting to 192.168.1.77:6650
03-05 15:36:11.080 17152-17181/com.example.bla.psedowifidims I/System.out: Received: WIFI
03-05 15:36:11.080 17152-17181/com.example.bla.psedowifidims I/System.out: Client expecting disconnect.
03-05 15:36:11.080 17152-17181/com.example.bla.psedowifidims I/System.out: Expecting disconnect.
03-05 15:36:11.590 17152-17181/com.example.bla.psedowifidims I/System.out: Killing wifi
03-05 15:36:16.660 17152-17181/com.example.bla.psedowifidims I/System.out: Enableing wifi
03-05 15:36:31.760 17152-17181/com.example.bla.psedowifidims I/System.out: Conecting to 192.168.1.77:6650
03-05 15:36:51.550 17152-17181/com.example.bla.psedowifidims I/System.out: Received: Hi wififims
03-05 15:36:56.780 17152-17181/com.example.bla.psedowifidims I/System.out: Received: IFI
如最後一行所示,第二消息在重新連接有缺陷後發送。它應該是「無線網絡」。如果我讓了,而程序運行,比方說5分鐘,突然失蹤的人物帶有另一條消息:
03-05 15:52:32.480 17152-17181/com.example.bla.psedowifidims I/System.out: Received: WWWWWWWWWWWWIFI
服務器
這裏顯示的監聽服務器:
public void startListening(int port) {
this.port = port;
canceled_ = false;
new Thread(() -> {
try {
System.out.println("Listening for incomming connections on port " + port);
serverSocket_ = new ServerSocket(port);
while (!canceled_) {
ServerClient serverClient = new ServerClient(serverSocket_.accept(), networkReceiver, server_);
serverClient.listen();
serverClient.setIdWithoutTransmission(Long.toString(clientId++));
this.ServerClientList_.add(serverClient);
networkReceiver.onNewClient(serverClient.getId());
System.out.println("Client connected from:" + serverClient.getClientSocket().getInetAddress() +
serverClient.getClientSocket().getPort());
}
} catch (IOException e) {
handleDisconnect();
}
}).start();
}
這組本地ServerClient處於監聽狀態:
public void listen() {
this.canceled_ = false;
new Thread(() -> {
while (!canceled_) {
try {
if (clientSocket_ == null) {
System.out.println("Socket is null, returning from listening");
return;
}
clientSocket_.setSoTimeout(0);
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(clientSocket_
.getInputStream()));
String msg = inFromClient.readLine();
if (msg == null) {
super.handleDisconnect();
return;
}
if (handleMessage(msg))
continue;
networkReceiver.onNewMessage(msg);
} catch (IOException e) {
super.handleDisconnect();
}
}
}).start();
}
當服務器發送到客戶端:
public void transmitMessage(String id, String msg) {
for (ServerClient ServerClient : ServerClientList_) {
System.out.println("Does " + id + " equals "+ ServerClient.getId());
if (ServerClient.getId().equals(id)) {
ServerClient.transmitMessage(msg);
return;
}
}
System.out.println("Couldn't find ServerClient.");
}
並在serverclient的實際方法:
public void transmitMessage(String message) {
if (clientSocket_ == null || !clientSocket_.isBound()) {
System.out.println("Not connected, can't transmit. Make sure you are connected to the host\nClientsocket " +
"is null or not bound");
return;
}
DataOutputStream outToServer = null;
try {
outToServer = new DataOutputStream(clientSocket_.getOutputStream());
outToServer.writeBytes(message + '\n');
} catch (IOException e) {
System.out.println("Error while writing to socket - message not delivered");
}
}
處理服務器上的斷開(客戶端發送該處理的消息)。
private boolean handleMessage(final String msg) {
if (msg.equals(EXPECT_DISCONNECT_MSG)) {
EXPECT_DISCONNECT_FLAG(true);
return true;
}
而當ServerClients監聽然後捕獲該異常,它然後看見升起的國旗,並呼籲:
protected void handleExpectedDisconnect() {
server_.lossOfClient(this);
this.canceled_ = true;
finalizeSockets();
}
的lossOfClient很簡單:
public void lossOfClient(final ServerClient serverClient) {
this.ServerClientList_.remove(serverClient);
System.out.println("Removed client with ID " + serverClient.getId());
System.out.println("Size: " + server_.getServerClientList().size());
}
客戶
客戶端初始化機智^ h
public void connectAndListen(String host, int port) {
this.canceled_ = false;
try {
System.out.println("Conecting to " + host + ":" + port);
clientSocket_ = new Socket(host, port);
clientSocket_.setSoTimeout(2000);
listen();
} catch (IOException e) {
System.out.println("Socket error - restarting");
}
}
public void listen() {
this.canceled_ = false;
new Thread(() -> {
while (!canceled_) {
try {
if (clientSocket_ == null) {
System.out.println("Socket is null, returning from listening");
return;
}
clientSocket_.setSoTimeout(0);
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(clientSocket_
.getInputStream()));
String msg = inFromClient.readLine();
if (msg == null) {
super.handleDisconnect();
return;
}
if (handleMessage(msg))
continue;
networkReceiver.onNewMessage(msg);
} catch (IOException e) {
super.handleDisconnect();
}
}
}).start();
}
和分離式:
public void disconnect() {
try {
if (clientSocket_ != null && clientSocket_.isBound()) {
System.out.println("Client expecting disconnect.");
EXPECT_DISCONNECT_FLAG(true);
transmitMessage(EXPECT_DISCONNECT_MSG);
Thread.sleep(500);
}
finalizeSockets();
} catch (InterruptedException e) {
System.out.println("Coudln't inform receiver about expected disconnect.");
}
}
public void finalizeSockets() {
if (clientSocket_ != null && clientSocket_.isBound()) {
try {
if (!clientSocket_.isClosed())
clientSocket_.close();
} catch (IOException e) {
System.out.println("Couldn't close clientsocket");
}
clientSocket_ = null;
}
}
可有人告訴我,我在做什麼錯?爲什麼在斷開連接/重新連接之後收到的消息(雙方都是新套接字)無法傳輸整個消息?
編輯:
試圖刷新的OutputStream,以確保所有字節發送,儘管這並沒有幫助。 此致敬禮。
編輯II
嘗試:
DataOutputStream outToServer = null;
BufferedReader inFromClient = null;
,只有創建他們時,他們是空。當套接字關閉時,這些設置爲空。同樣的問題:
03-05 18:05:00.000 11383-11427/com.example.bla.psedowifidims I/System.out:
Conecting to 192.168.1.77:6650
03-05 18:05:06.470 11383-11428/com.example.bla.psedowifidims I/System.out: Received: Hi wififims
03-05 18:05:11.490 11383-11428/com.example.bla.psedowifidims I/System.out: Received: WIFI
03-05 18:05:11.490 11383-11428/com.example.bla.psedowifidims I/System.out: Client expecting disconnect.
03-05 18:05:11.490 11383-11428/com.example.bla.psedowifidims I/System.out: Expecting disconnect.
03-05 18:05:12.000 11383-11428/com.example.bla.psedowifidims I/System.out: Killing wifi
03-05 18:05:17.090 11383-11428/com.example.bla.psedowifidims I/System.out: Enableing wifi
03-05 18:05:32.180 11383-11428/com.example.bla.psedowifidims I/System.out: Conecting to 192.168.1.77:6650
03-05 18:05:51.530 11383-13368/com.example.bla.psedowifidims I/System.out: Received: i wififims
03-05 18:05:56.560 11383-13368/com.example.bla.psedowifidims I/System.out: Received: IFI
03-05 18:06:38.300 11383-11428/com.example.bla.psedowifidims I/System.out: Received: HWHi wififims
03-05 18:06:43.340 11383-13368/com.example.bla.psedowifidims I/System.out: Received: WIFI
編輯III 有了一絲Wireshark的我可以看到,有時像「WIFI」的消息被分裂成兩個包,W於一體,並在IFI其他。這看起來的原因,所以我嘗試:
public void listen(){
....
byte[] arbytes = new byte[inFromServer.readInt()];
int length = arbytes.length;
inFromServer.read(arbytes,0,length);
....
}
和發射
public void transmitMessage(String message) {
....
try {
if(outToServer == null)
outToServer = new DataOutputStream(clientSocket_.getOutputStream());
byte[] databyes = message.getBytes(Charset.forName("UTF-8"));
outToServer.writeInt(databyes.length);
outToServer.write(databyes);
} catch (IOException e) {
System.out.println("Error while writing to socket - message not delivered");
}
}
雖然仍然沒有運氣:
03-05 20:01:10.810 27328-27353/com.example.bla.psedowifidims I/System.out:
Conecting to 192.168.1.77:6650
03-05 20:01:21.600 27328-27354/com.example.bla.psedowifidims I/System.out: Received: WIFI
03-05 20:01:21.600 27328-27354/com.example.bla.psedowifidims I/System.out: Client expecting disconnect.
03-05 20:01:21.600 27328-27354/com.example.bla.psedowifidims I/System.out: Expecting disconnect.
03-05 20:01:22.110 27328-27354/com.example.bla.psedowifidims I/System.out: Killing wifi
03-05 20:01:27.200 27328-27354/com.example.bla.psedowifidims I/System.out: Enableing wifi
03-05 20:01:42.270 27328-27354/com.example.bla.psedowifidims I/System.out: Conecting to 192.168.1.77:6650
03-05 20:01:42.290 27328-27354/com.example.bla.psedowifidims I/System.out: Percent bad: 0.0
03-05 20:02:01.560 27328-28467/com.example.bla.psedowifidims I/System.out: Received: ififims�������
嘿,你會改變這outToServer.writeBytes(消息+'\ n'); 在transmitMessage中向此outToServer.writeBytes((message +'\ n')。getBytes()); – Mehdi
那麼,writeBytes接受一個字符串,不是嗎?因此,如果我使用getBytes,我必須使用它的String.ValueOf,然後它簡單地接收爲「Received:[B @ 682a0b20」:( –
)將inFromServer更改爲DataInputStream並使用readFully並告訴我請 – Mehdi