【发布时间】:2015-04-14 01:01:32
【问题描述】:
我正在用 java 制作一个安全的 VOIP 程序,我选择使用 netty 来简化我的网络。到目前为止,这实际上是该项目最大的时间成本。VOIP 在 localhost 上运行良好,但是当我转到网络上的另一台计算机时,发生了一些奇怪的事情。现在只有两个数据包,50 个用于聊天,51 个用于语音样本。该程序可以正常运行几帧,然后我收到随机数据包编号和无效大小。我不确定是什么原因造成的。..
这是传输数据包的类:
package com.io;
import com.gui.VoiceCallFrame;
import com.net.Session;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.TargetDataLine;
/**
* @author Colby
*/
public class VoiceTransmitHandler implements VoiceIOHandler {
public VoiceTransmitHandler(String name, Session remote) {
this.remote = remote;
VoiceCallFrame frame = new VoiceCallFrame(name, this);
frame.setVisible(true);
}
private Session remote;
private boolean running;
public void start() {
running = true;
new Thread() {
@Override
public void run() {
try {
AudioFormat format = new AudioFormat(16000.0f, 16, 1, true, true);
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
TargetDataLine microphone = (TargetDataLine) AudioSystem.getLine(info);
try {
microphone.open(format);
microphone.start();
byte[] buf = new byte[4000];
do {
int len = microphone.read(buf, 0, buf.length);
ByteBuf packet = ByteBufAllocator.DEFAULT.buffer();
packet.writeByte(51);
packet.writeShort(len);
packet.writeBytes(buf, 0, len);
System.out.println("Send: " + packet.readableBytes());
remote.writeTCP(packet);
} while (running);
} finally {
microphone.close();
}
} catch (LineUnavailableException e) {
running = false;
e.printStackTrace();
}
}
}.start();
}
public void stop() {
running = false;
}
}
这里是数据包被解码的地方:
@Override
public void readTCP(ByteBuf msg) {
if (opcode == -1) {
if (msg.readableBytes() < 3) {
return;
}
opcode = msg.readUnsignedByte();
length = msg.readUnsignedShort();
}
if (msg.readableBytes() < length) {
return;
}
byte[] data = new byte[length];
msg.readBytes(data);
try {
System.out.println("Packet received " + opcode + ":" + length);
switch(opcode) {
case 51://Voice received
if(vrh == null) {
vrh = new VoiceReceiveHandler(host.getHostAddress());
vrh.start();
}
vrh.playLater(data);
break;
}
} finally {
opcode = length = -1;
}
}
在我的 ChannelInboundHandlerAdapter 中调用它的位置
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
session.readTCP((ByteBuf) msg);
}
我完全看不出我的数据包可能在哪里弄乱了。在我正确传输和解码它们时,它看起来像我。如果需要更多相关代码,请留言。
【问题讨论】:
-
msg.readBytes总是填满整个数组,还是像InputStream.read那样返回可变数量的字节? -
它似乎填满了整个数组:"public abstract ByteBuf readBytes(byte[] dst) 将此缓冲区的数据传输到从当前 readerIndex 开始的指定目的地,并将 readerIndex 增加传输的字节数(= dst.length)。抛出:IndexOutOfBoundsException - 如果 dst.length 大于 this.readableBytes"
-
只是补充一下,这里是输出: Packet received 51:4000 Packet received 51:4000 Packet received 51:4000 Packet received 64:576
-
您似乎正在写入默认字节和短裤(将被签名)但读取无符号字节。你有没有试过把这些对齐,所以读和写是一样的?
-
@Mick 在 java 中没有读取有符号值的特殊方法。如果我错了,请纠正我
标签: java networking netty voip packet