SocketChannel阻塞服务端缓冲区未清空导致重复输出问题求助
问题根源与解决方案
问题出在哪?
你的服务器代码里的reqString是一个全局静态的StringBuffer,每次接收到客户端的字符都会调用reqString.append(c)追加内容,但从来没有清空过它!这就导致每次新接收的字符都会拼在旧内容后面,出现你看到的helloworld、helloworldthis这类拼接结果。
而ByteBuffer的clear()和flip()操作是没问题的——这些只是重置缓冲区的读写位置,和reqString的累加完全是两回事。
修复方案(两种可选)
方案1:每次处理完消息后清空reqString
在打印完消息之后,调用reqString.setLength(0)来清空StringBuffer的内容:
public class EchoServer_1 { private static ByteBuffer buffer = ByteBuffer.allocate(1024); private static StringBuffer reqString = new StringBuffer(); public static void main(String[] args) throws IOException { ServerSocketChannel serverSocketChannel = null; int serverPort = 10007; try{ serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.socket().bind(new InetSocketAddress (serverPort)); serverSocketChannel.configureBlocking(true); System.out.println("Port number: " + serverPort); System.out.println("Waiting for connection .."); SocketChannel sc = serverSocketChannel.accept(); System.out.println ("Incoming connection from: " + sc.socket().getRemoteSocketAddress( )); while (true) { buffer.clear(); sc.read(buffer); buffer.flip(); while(buffer.hasRemaining()) { char c = (char) buffer.get(); if (c == '\r' || c == '\n') break; reqString.append(c); } log("Message received: " + reqString); // 新增:清空StringBuffer,准备接收下一条消息 reqString.setLength(0); } }catch (IOException ex) { if (serverSocketChannel != null) serverSocketChannel.close(); System.err.println("Client has disconneted"); } } private static void log(String str) { System.out.println(str); } }
方案2:将reqString的声明移到循环内部
这样每次循环都会创建一个新的StringBuffer,自然不会有旧数据残留:
public class EchoServer_1 { private static ByteBuffer buffer = ByteBuffer.allocate(1024); public static void main(String[] args) throws IOException { ServerSocketChannel serverSocketChannel = null; int serverPort = 10007; try{ serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.socket().bind(new InetSocketAddress (serverPort)); serverSocketChannel.configureBlocking(true); System.out.println("Port number: " + serverPort); System.out.println("Waiting for connection .."); SocketChannel sc = serverSocketChannel.accept(); System.out.println ("Incoming connection from: " + sc.socket().getRemoteSocketAddress( )); while (true) { // 移到这里:每次循环新建一个StringBuffer StringBuffer reqString = new StringBuffer(); buffer.clear(); sc.read(buffer); buffer.flip(); while(buffer.hasRemaining()) { char c = (char) buffer.get(); if (c == '\r' || c == '\n') break; reqString.append(c); } log("Message received: " + reqString); } }catch (IOException ex) { if (serverSocketChannel != null) serverSocketChannel.close(); System.err.println("Client has disconneted"); } } private static void log(String str) { System.out.println(str); } }
额外说明
客户端的代码逻辑是正确的——每次发送完数据都会调用buffer.clear()重置缓冲区,所以不会出现类似的问题。
修复之后,服务器就能输出预期的单独消息了:
Message received: hello Message received: world Message received: this ...
内容的提问来源于stack exchange,提问作者Jose Castano Pardo
相关产品推荐
相关产品推荐

