java - 客户端套接字没有准确接收到服务器端套接字发送的内容

标签 java android sockets

我一直在开发一个类似于对讲机的 Android 音频聊天程序。用户按下通话按钮后,录音机开始记录用户所说的内容,并通过套接字将音频字节写入远程服务器。在服务器端,服务器套接字只是将它收到的音频字节发送到其他客户端套接字。

我没有很好的方法来控制这些套接字的行为。比如识别一个client socket属于哪个用户?套接字除了它写入的数据外,没有任何字段来承载附加信息。所以最后,我想出解决方案是使用传输音频数据的同一个套接字来传输用户名字符串之类的东西。这很有效,因为在客户端套接字成功创建到服务器套接字的连接的情况下,android 客户端会发送用户名字符串。

当我尝试发送用户名字符串以通知其他正在通话的客户端时,当用户按下通话按钮时,灾难就发生了。让我举个例子来说明这一点:

  1. 名为“user1”的用户按下通话按钮开始通话。
  2. 应用程序向服务器端发送字符串“usr:user1”。
  3. 然后开始发送录音机生成的音频数据。

在服务器端,服务器接收到确切的“user1”和以下音频数据,并重新发送给其他连接的客户端。但问题是客户端似乎并没有一直接收到“usr:user1”。

这是我检查接收到的数据的方法:

 is = socket.getInputStream();
 byte[] buffer = new byte[minBufSize];
 numOfReceived = is.read(buffer);
 if(numOfReceived!=-1&&numOfReceived!=minBufSize){
     byte[] ub = new byte[numOfReceived];
     for(int i=0;i<numOfReceived;i++){
         ub[i]=buffer[i];
     }
     String usersString = new String(ub, "UTF-8");
     if(usersString.contains("hj:")){
         System.out.println("current:");
         final String userOfTalking=usersString.substring(3,usersString.length());
         runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 whoIsTalking.setText(userOfTalking+" is talking");
                 whoIsTalking.setVisibility(View.VISIBLE);
             }
         });
         continue;
     }

其实我并不知道输入流中包含的是音频数据还是字符串数据。所以我尝试使用 inputstream.read() 的返回来找出输入流读取了多少字节:

  • 如果返回值不等于 -1(套接字关闭)或缓冲区大小,我在 outputstream.write 中设置,然后我假设它是一个字符串。

但这是非常不可靠的。例如,如果我循环执行命令 socket.getoutstream.write(buffer,0,100),那么我应该从输入流中读取长度为 100 的缓冲区。但事实并非如此。我经常得到长度为 60、40 或任何小于 100 的缓冲区。

这就像输出流并没有像它声明的那样准确地发送 100 字节的数据。所以我的字符串数据只是与以下音频数据混合。因此,当应用程序在刚连接到服务器时发送用户名时,其他客户端将收到正确的字符串,因为没有后续的音频数据干扰它。

你们能给我一些意见吗?我的猜测对吗?我怎么解决这个问题?当用户按下通话按钮以在发送音频数据之间留出一些空间以防它们混合时,在应用程序发送用户名字符串后,我设法调用了 Thread.sleep(300)。但它不起作用。非常感谢任何帮助!

最佳答案

如果我已经正确阅读了这个...您发送了正好 100 个字节,但随后的 read 没有得到 100,它变少了吗?

这可能有多种原因。一是您在编写时没有调用 flush()。如果是这种情况,那么您就有了错误,您需要在发送代码中调用适当的 flush()

或者,这可能是因为操作系统正在对数据包之间的数据进行分段。这对于小数据包(100 字节)不太可能,但对于大数据包很可能/必需...

你永远不应该依赖于一次读取中出现的所有数据......你需要多次读取来组装所有数据。

关于java - 客户端套接字没有准确接收到服务器端套接字发送的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39183338/

相关文章:

java - 错误: Unable to access jarfile.编码问题

java - 比较枚举与列表 Thymeleaf

android - Espresso,使用登录屏幕测试快乐路径

linux - SOCK_DGRAM 和 SOCK_STREAM 在上下文 AF_UNIX 套接字中的用途是什么?

php - Ratchet WebSocket 无法在 Vagrant 机器上运行

java - 将字节数组转换为具有同等字节数的字符串

java - Twitter4J 上最多 20 个好友信息

java - 如何检测整个应用程序是否在android中关闭

android - 在 Android 11 上编写许多文件

c - 使用 lseek 函数更改 c 中的文件位置后损坏的文件(大小相同但内容损坏)