我有一个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