2017-03-05 36 views
1

我有一个android设备和一个服务器。服务器可以传输一条消息,告诉设备从wifi上断开连接。要快速知道这是怎么做的话,这里有一个psudo序列图:在缓冲读取器中缺少第一个字符

Pseudo sd

现在,有趣的是,当客户端重新连接,服务器发送一个消息,有时该消息丢失第一字符,有时它是下一个消息。无论如何,在客户端重新连接之后它发生的很快。

而且例如环这里示出,从服务器侧看出:

 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������� 
+0

嘿,你会改变这outToServer.writeBytes(消息+'\ n'); 在transmitMessage中向此outToServer.writeBytes((message +'\ n')。getBytes()); – Mehdi

+0

那么,writeBytes接受一个字符串,不是吗?因此,如果我使用getBytes,我必须使用它的String.ValueOf,然后它简单地接收为“Received:[B @ 682a0b20”:( –

+0

)将inFromServer更改为DataInputStream并使用readFully并告诉我请 – Mehdi

回答

0

好了 - 我经历了很多试验去了。我尝试手动发送要传输的数字字节,然后是数据,然后在客户端做相应的处理。

虽然这个工作,当一个TCP重传发生时,不知何故它得到了重传包的大小错误。这对于WriteUTF等是一样的。

不知何故 - 经过大量尝试后,我将变送器改为使用PrintWriter。

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; 
    } 

    try { 
     if (outToServer == null) 
      outToServer = new DataOutputStream(clientSocket_.getOutputStream()); 


     PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(clientSocket_.getOutputStream())), true); 
     pw.println(message); 
     pw.flush(); 

    } catch (IOException e) { 
     System.out.println("Error while writing to socket - message not delivered"); 

    } 

} 

现在一切正常 - 也在重传过程中。 如果有人能告诉我为什么这个工程,我真的很感激它!