蓝牙连接;无法正确发送字符串

Posted

技术标签:

【中文标题】蓝牙连接;无法正确发送字符串【英文标题】:Bluetooth-connection; can't send strings properly 【发布时间】:2012-02-03 19:49:33 【问题描述】:

当我需要将字符串从服务器蓝牙套接字发送到客户端蓝牙套接字时,我的程序出现问题。 只要我一次只发送一个字符串(例如聊天),一切正常,但如果我需要在短时间内编写更多字符串(交换信息),字符串将不会与客户端代码分离.例如,如果我正在发送“FirstUser”并且在“SecondUser”之后,客户端不会读取“FirstUser”然后是“SecondUser”。它将读取“FirstUserSecondUser”。如何避免这种行为?

编辑:如果我让线程在能够发送新消息之前休眠,它会读取正确的字符串,但这个解决方案不能满足我的需要。

服务器代码:发送到所有客户端(已编辑)

   public synchronized void sendToAll(String message)
   
    try 
        Thread.sleep(100);
     catch (InterruptedException e1) 
        e1.printStackTrace();
    

    publishProgress(message);
    for(OutputStream writer:outputList) 
        try 
            writer.write(message.getBytes());
            writer.flush();
         catch (IOException e) 
            System.out.println("Some-Error-Code");
        
    

服务器代码:从客户端读取:

   public void run() 
    String nachricht;
    int numRead;
    byte[] buffer = new byte[1024];
    while (runningFlag) 
    
        try 
            if((numRead = inputStream.read(buffer)) >= 0)  
                nachricht = new String(buffer, 0, numRead);
                serverThread.handleMessage(nachricht); 
            
            
             catch (IOException e) 
                this.cancel();
                e.printStackTrace();
            
     
 

客户端代码:从服务器读取(已编辑)

@Override
    protected Void doInBackground(Integer... ints)     
        String nachricht = new String();
        byte[] buffer = new byte[1024];
        int numRead;
        while (runningFlag) 
        
            try 
                if(((numRead = inputStream.read(buffer)) >= 0))  
                    nachricht = new String(buffer, 0, numRead);
                    publishProgress(nachricht);
                
            
             catch (IOException e) 
                clientGame.finish();
                e.printStackTrace();
                                  
        
        return null;

客户端代码:写入服务器

public synchronized void write(String nachricht)
    
        try 
            Thread.sleep(100);
         catch (InterruptedException e1) 
            e1.printStackTrace();
        

        try 
            outputStream.write(nachricht.getBytes());
            outputStream.flush();
         catch (IOException e) 
            this.cancel();
            e.printStackTrace();
        
    

感谢每一个小小的帮助:)。

【问题讨论】:

您的服务器是否向客户端发送消息,反之亦然? 双向循环。在客户端或服务器能够发送另一个字符串之前,我暂时“解决”了 Thread.sleep(100) 的问题。但这并不是一个很好的解决方案。 您是否正在刷新所有已发送的消息? 是的,我愿意。似乎它写入消息的速度如此之快,以至于 read() 函数只能看到一个传入的字符串。 它不是人,而是机器。没有什么叫“这么快”。到目前为止,我无法帮助您提供您提供的信息。研究流是如何工作的,并确保你正在冲洗所有东西。也许,也可以发布更多代码。 【参考方案1】:

您需要封装数据项以避免串联。 这意味着您必须在继续之前写入和读取整个数据项。

你应该有一些实用方法来做到这一点,而不是直接使用 OutputStream 和 InputStream 的方法:

public static void writeItem(OutputStream out, String s) throws IOException

    // Get the array of bytes for the string item:
    byte[] bs = s.getBytes(); // as bytes
    // Encapsulate by sending first the total length on 4 bytes :
    //   - bits 7..0 of length
    out.write(bs.length);      // modulo 256 done by write method
    //   - bits 15..8 of length
    out.write(bs.length>>>8);  // modulo 256 done by write method
    //   - bits 23..16 of length
    out.write(bs.length>>>16); // modulo 256 done by write method
    //   - bits 31..24 of length
    out.write(bs.length>>>24); // modulo 256 done by write method
    // Write the array content now:
    out.write(bs); // Send the bytes
    out.flush();


public static String readItem(InputStream in) throws IOException

    // first, read the total length on 4 bytes
    //  - if first byte is missing, end of stream reached
    int len = in.read(); // 1 byte
    if (len<0) throw new IOException("end of stream");
    //  - the other 3 bytes of length are mandatory
    for(int i=1;i<4;i++) // need 3 more bytes:
    
        int n = in.read();
        if (n<0) throw new IOException("partial data");
        len |= n << (i<<3); // shift by 8,16,24
    
    // Create the array to receive len bytes:
    byte[] bs = new byte[len];
    // Read the len bytes into the created array
    int ofs = 0;
    while (len>0) // while there is some byte to read
    
        int n = in.read(bs, ofs, len); // number of bytes actually read
        if (n<0) throw new IOException("partial data");
        ofs += n; // update offset
        len -= n; // update remaining number of bytes to read
    
    // Transform bytes into String item:
    return new String(bs);

然后,您可以使用这些方法为服务器和客户端读取和写入您的字符串项目。

【讨论】:

关于 OutputStream.flush() 的文档说“这个实现什么都不做。”这很正常,因为 OutputStream 只是一个抽象类。实际的类(FileOutputStream, SocketOutputStream, ...)会覆盖这个方法来做一些事情。 我看不懂你的代码。你能试着解释一下吗?例如,我以前从未见过 '>>> 和 '|=' 运算符。为什么会有串联?为什么flush()不能解决问题? >>> 运算符将位向右移动,而不复制符号位。而 >> 将复制符号位。例如:1000..0100 >> 2 == 111000..01 而 1000..0100 >>> 2 == 001000..01 我今天尝试了您的代码,它似乎运行良好。在接下来的几天里,我将对其进行更多测试并报告我的使用体验。谢谢队友:) 我不知道为什么我的这个命题是-1,这似乎解决了问题,但仍然没有被选为解决方案......

以上是关于蓝牙连接;无法正确发送字符串的主要内容,如果未能解决你的问题,请参考以下文章

笔记本蓝牙无法接收文件,只可以发送。

如何正确地通过蓝牙从 Android 向 Arduino 连续发送消息

手机连接蓝牙耳机无法建立通信

没有通过蓝牙收到 EA 通知

求助,win10蓝牙显示已配对,但是没有连接

Android蓝牙串口通信控制Arduino全彩呼吸灯