我的问题是关于JAVANIO客户端服务器消息传递,我不确定从技术上定义这个问题,但是:看起来buffer正在缓存数据,当它完成后,它会一起发送,这是令人不安的逻辑:
private void sendCreate(String line,SocketChannel from)
/* A new client wishes to join the world.
This requires the client to find out about the existing
clients, and to add itself to the other clients' worlds.
Message format: create name xPosn zPosn
Store the user's name, extracted from the "create" message
*/
{ StringTokenizer st = new StringTokenizer(line);
st.nextToken(); // skip 'create' word
userName = st.nextToken();
String xPosn = st.nextToken(); // don't parse
String zPosn = st.nextToken(); // don't parse
// request details from other clients
sendBroadcastMessage( "wantDetails " + achannel.socket().getInetAddress() + " " + port,from);
// tell other clients about the new one
sendBroadcastMessage( "create " + userName + " "+xPosn+" "+zPosn,from);
} // end of sendCreate()负责从服务器广播消息的方法:
private void sendBroadcastMessage(String mesg, SocketChannel from) {
prepWriteBuffer(mesg);
Iterator i = clients.iterator();
while (i.hasNext()) {
SocketChannel channel = (SocketChannel) i.next();
if (channel != from)
channelWrite(channel, writeBuffer);
}
}我假设这应该发送第一条消息,即sendBroadcastMessage( "wantDetails“+ achannel.socket().getInetAddress() +”“+ port,from);但这不是,它似乎在等待其他方法调用,即sendBroadcastMessage( "create”+ userName + "+xPosn+“"+zPosn,from);然后将这两条消息作为一条消息发送,这是影响应用程序logic.ideally的一条消息,或者它应该在第一次调用sendBroadcastMessage之后发送第一条消息,然后当客户端收到第一个调用时,应该处理其他调用。
以下是在sendBroadcastMessage()中使用的方法:
private void prepWriteBuffer(String mesg) {
// fills the buffer from the given string
// and prepares it for a channel write
writeBuffer.clear();
writeBuffer.put(mesg.getBytes());
writeBuffer.putChar('\n');
writeBuffer.flip();
}
private void channelWrite(SocketChannel channel, ByteBuffer writeBuffer) {
long nbytes = 0;
long toWrite = writeBuffer.remaining();
// loop on the channel.write() call since it will not necessarily
// write all bytes in one shot
try {
nbytes += channel.write(writeBuffer);
} catch (ClosedChannelException cce) {
cce.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
// get ready for another write if needed
writeBuffer.rewind();
}请建议一些解决方案。
谢谢,
摇摆拉拉
编辑:这个怎么样,我从一些聊天应用上得到了这个补丁:
private void prepWriteBuffer(String mesg) {
// fills the buffer from the given string
// and prepares it for a channel write
writeBuffer.clear();
writeBuffer.put(mesg.getBytes());
writeBuffer.putChar('\n');
writeBuffer.flip();
}
// called needs to remove the channel if it fails, otherwise it will fail forever.
private void channelWrite(SocketChannel channel, ByteBuffer writeBuffer) {
long nbytes = 0;
long toWrite = writeBuffer.remaining();
// loop on the channel.write() call since it will not necessarily
// write all bytes in one shot
try {
while (nbytes != toWrite) {
nbytes += channel.write(writeBuffer);
try {
Thread.sleep(CHANNEL_WRITE_SLEEP);
} catch (InterruptedException e) {
}
}
} catch (ClosedChannelException cce) {
} catch (Exception e) {
}
// get ready for another write if needed
writeBuffer.rewind();
}发布于 2010-11-27 04:56:11
也许你是有意
while(writeBuffer.remaining()>0)
channel.write(writeBuffer);然而,您的问题似乎是您假设在消息之间存在某种类型的魔法标记。但是,并不存在这样的分隔符。一个流就是一个字节流。当你在阻塞模式下读取时,你会得到至少一个字节,你可能会得到更多,这可能会跨越多次写入,但除非你在流中包含你希望消息开始和结束的地方,否则你将无法知道。
一种简单的方法是在消息的开头写入消息的长度,并读取最多一条消息,直到您获得所有消息。就像这样。
private void prepWriteBuffer(String mesg) {
// fills the buffer from the given string
// and prepares it for a channel write
writeBuffer.clear();
byte[] bytes = mesg.getBytes());
writeBuffer.putInt(bytes.length);
writeBuffer.put(bytes);
writeBuffer.flip();
}
// called needs to remove the channel if it fails, otherwise it will fail forever.
private void channelWrite(SocketChannel channel, ByteBuffer writeBuffer) throws IOException {
while(writeBuffer.remaining()>0)
channel.write(writeBuffer);
writeBuffer.rewind();
}https://stackoverflow.com/questions/4288444
复制相似问题