【发布时间】:2017-01-04 03:10:32
【问题描述】:
我一直在开发一个 Android 音频聊天程序,其行为类似于对讲机。用户按下通话按钮后,录音机开始记录用户所说的内容,并通过套接字将音频字节写入远程服务器。在服务器端,服务器套接字只是将它接收到的音频字节发送到其他客户端套接字。
我没有控制这些套接字行为的好方法。例如,要识别一个客户端套接字属于哪个用户?套接字除了写入的数据外,没有任何字段来携带附加信息。所以最后,我想出解决方案是使用传输音频数据的相同套接字来传输用户名字符串之类的东西。这很好用,因为在客户端套接字成功创建到服务器套接字的连接的情况下,android客户端会发送一个用户名字符串。
当我尝试发送用户名字符串以通知其他正在讲话的客户时,当用户按下通话按钮时,灾难发生了。让我举一个例子来说明这一点:
- 名为“user1”的用户按下通话按钮进行通话。
- 应用程序将字符串“usr:user1”发送到服务器端。
- 然后开始发送录音机生成的音频数据。
在服务器端,服务器接收到确切的“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) 以便在发送音频数据之间留出一些空间,以防它们混合。但它不起作用。非常感谢任何帮助!
【问题讨论】:
-
哇,这是一堵文字墙。确实太长了,没看。无论如何,您需要minimal reproducible example。
-
@JonathonReinhart 最小示例对于这个特定问题不太可能可行。建设性的输入将包括复制编辑。我尽力了。
-
@user1870797 我尽力编辑。如果可能的话,你认为你可以删除一些对澄清问题没有特别有用的细节吗?这可能会让一些人更容易解决你的问题。您还可以清理您的接收器 sn-p(它有一个杂散的
continue和一些不平衡的 {})并包含您的 sending 代码的相关部分吗?另外,也许很明显,但是您使用的是 TCP(不是 UDP),对吗?您的问题可能会在此期间被搁置,但不要担心,它可以在稍微清理一下后重新打开。 -
@Jason C,感谢你们的建议和 Jason C 的编辑。抱歉杀了你的编辑。我对stackoverflow的功能不太熟悉。但非常感谢您的努力。我正在重新编辑我的问题以使其更清晰。
-
@Jason C 是的,它们是 tcp 套接字,我会添加这个。