从套接字通道读取字符串
Posted
技术标签:
【中文标题】从套接字通道读取字符串【英文标题】:Read string from socket channel 【发布时间】:2015-03-07 18:08:08 【问题描述】:喂,
我有以下代码:
public AppThread(SocketChannel socketChannel)
this.socketChannel=socketChannel;
public void run()
try
ByteBuffer bb = ByteBuffer.allocate(11);
socketChannel.read(bb);
//byte[] b = new byte[bb.capacity()];
// bb.get(b, 0, 11);
System.out.println(bb.toString());
byte[] a = new byte[11];
CharBuffer cb = bb.asCharBuffer();
System.out.println(cb);
bb.get(a);
App app=new App();
// String an = new String(b);
//String zodie = Zodie.getZodie(an);
//b = new byte[zodie.length()];
//b = zodie.getBytes();
bb.clear();
//bb.put(b);
socketChannel.write(bb);
socketChannel.close();
catch(IOException e)
System.err.println("Server comunication error : "+e.getMessage());
还有接收字符串并返回字符串的zodie静态方法。
如何将字符串写入 SocketChannel 以将其作为参数传递给 zodiac 静态方法。
我提到在客户端我发送了一个字节数组,我已经检查过了,没关系。
客户端:
byte[] a = an.getBytes();
System.out.println(new String(a));
ByteBuffer bb=ByteBuffer.allocate(11);
// Varianta 1
bb.put(a);
// Varianta 2
// LongBuffer lb=bb.asLongBuffer();
// lb.put(0,m).put(1,n);
try
sc.write(bb);
bb.clear();
sc.read(bb);
// Varianta 1
//a = new byte[bb.remaining()];
zodie=bb.toString();
// Varianta 2
// r=lb.get(0);
System.out.println("Zodia : "+ zodie);
sc.close();
此致,
我收到服务器错误:
Server ready...
java.nio.HeapByteBuffer[pos=1 lim=11 cap=11]
Exception in thread "pool-1-thread-1" java.nio.BufferUnderflowException
at java.nio.HeapByteBuffer.get(Unknown Source)
at java.nio.ByteBuffer.get(Unknown Source)
at server.AppThread.run(AppThread.java:27)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
【问题讨论】:
【参考方案1】:你的问题在 bb.get(a);
您将 11 个字符的数组指定为参数,因此 get() 方法期望 bb 包含 11 个字符,但它只包含 1 个。
原因是当您向套接字写入 11 个字符时,它们不能保证一次全部到达。他们可以分成小组到达,例如 1 和 10 或 5 和 6 等。
您需要查看和读取套接字并检查 read() 调用的结果。类似的东西:
for (;;)
int numberOfBytesRead =socket.read(buf);
if (numberOfBytesRead < 0) break;
【讨论】:
我为 (;;) System.out.println("xxx @@@ "); 插入了以下行int numberOfBytesRead =socketChannel.read(bb); System.out.println(numberOfBytesRead); if (numberOfBytesRead 我的错。客户端关闭连接时返回 -1。它可能会返回零,但您需要使用阻塞。更多信息:docs.oracle.com/javase/7/docs/api/java/nio/channels/…【参考方案2】:问题出在客户端。我使用了一个字符缓冲区作为包装器
Scanner scanner=new Scanner(System.in);
String m;
System.out.println("Enter the date (yyyy-mm-dd) :");
m=scanner.next()+" ";
CharBuffer c = CharBuffer.wrap(m);
System.out.println("Sending date ...: " + c);
ByteBuffer b = Charset.forName("ISO-8859-1").encode(c);
b.compact();
System.out.println("Bytebuffer has the capacity of "+
b.capacity() + "pointer position on bytebuffer is on: "+ b.position() + " and the limit is:" + b.limit());
b.flip();
在服务器端:
CharBuffer c;
ByteBuffer bb = ByteBuffer.allocate(11);
System.out.println("Server allocated a number of 11 octets to ByteBuffer");
socketChannel.read(bb);
bb.flip();//sets the Position to 0 and limit to the number of bytes to be read.
CharBuffer c = Charset.forName("ISO-8859-1").decode(bb);
System.out.println("Got " + c);
byte[] byteArray = new byte[11];
bb.get(byteArray);
System.out.println("Server got from client the string: " +new String(byteArray));
String an = new String(byteArray);
bb.clear();
【讨论】:
以上是关于从套接字通道读取字符串的主要内容,如果未能解决你的问题,请参考以下文章
从 Java NIO socketchannel 读取字节,直到到达标记