Java nio实现socket通信遇到的问题
新的连接可以正常连接,没有测试连接上限。
现在的问题是我想处理从客户端发送消息,服务端接收消息并发给客户端。
现在在服务端接收不到客户端发来的消息怎么办?
server端代码:
- Java code
import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.util.Calendar;import java.util.Iterator;public class TestServer { public static void main(String[] args) { new EchoServer(1982); }}class EchoServer implements Runnable { //要监听的端口号 private int port; //生成一个信号监视器 private Selector s; //读缓冲区 private ByteBuffer r_bBuf = ByteBuffer.allocate(1024); public EchoServer(int port) { this.port = port; try { s = Selector.open(); } catch (IOException e) { e.printStackTrace(); } new Thread(this).start(); } @Override public void run() { try { //生成一个ServerScoket通道的实例对象,用于侦听可能发生的IO事件 ServerSocketChannel ssc = ServerSocketChannel.open(); //将该通道设置为异步方式 ssc.configureBlocking(false); //绑定到一个指定的端口 ssc.socket().bind(new InetSocketAddress(port)); //注册特定类型的事件到信号监视器上 ssc.register(s, SelectionKey.OP_ACCEPT); System.out.println("The server has been launched..."); while(true) { //将会阻塞执行,直到有事件发生 System.out.println("监听新事件..."); s.select(); Iterator<SelectionKey> it = s.selectedKeys().iterator(); while(it.hasNext()) { SelectionKey key = it.next(); //key定义了四种不同形式的操作 switch(key.readyOps()) { case SelectionKey.OP_ACCEPT : dealwithAccept(key); break; case SelectionKey.OP_CONNECT : break; case SelectionKey.OP_READ : break; case SelectionKey.OP_WRITE : dealwithRead(key); break; } //处理结束后移除当前事件,以免重复处理 it.remove(); } } } catch (IOException e) { e.printStackTrace(); } } //处理接收连接的事件 private void dealwithAccept(SelectionKey key) { try { System.out.println("deal with new accept..."); ServerSocketChannel server = (ServerSocketChannel)key.channel(); SocketChannel sc = server.accept(); sc.configureBlocking(false); //注册读事件 sc.register(s, SelectionKey.OP_WRITE); System.out.println("deal with new accept2..."); } catch (IOException e) { e.printStackTrace(); } } //处理客户端发来的消息,处理读事件 private void dealwithRead(SelectionKey key) { try { SocketChannel sc = (SocketChannel)key.channel(); System.out.println("读入数据"); r_bBuf.clear(); System.out.println(r_bBuf.position()); sc.write(r_bBuf); System.out.println(r_bBuf.position()); r_bBuf.flip(); System.out.println(r_bBuf.asCharBuffer().toString()); r_bBuf.clear(); System.out.println("处理完毕..."); try { Thread.currentThread().sleep(10000000); } catch (InterruptedException e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } } private String getCurrentTime() { return Calendar.getInstance().toString(); }}client端代码
- Java code
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SocketChannel;public class TestClient { public static void main(String[] args) { new MiniClient("localhost", 1982); }}class MiniClient { private SocketChannel sc; private ByteBuffer w_bBuf; public MiniClient(String host, int port) { try { InetSocketAddress remote = new InetSocketAddress(host, port); sc = SocketChannel.open(); sc.connect(remote); if(sc.finishConnect()) { System.out.println("已经与服务器成功建立连接..."); } while(true) { if(!sc.isConnected()) { System.out.println("已经与服务器失去了连接..."); } BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String str = "123"; System.out.println("读入一行数据,开始发送..."); w_bBuf = ByteBuffer.wrap(str.getBytes()); w_bBuf.flip(); sc.write(w_bBuf); System.out.println("数据发送成功..."); w_bBuf.clear(); try { Thread.currentThread().sleep(10000000); } catch (InterruptedException e) { e.printStackTrace(); } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}在线等解决方案。
[解决办法]
//处理客户端发来的消息,处理读事件
private void dealwithRead(SelectionKey key) {
try {
SocketChannel sc = (SocketChannel)key.channel();
System.out.println("读入数据");
r_bBuf.clear();
System.out.println(r_bBuf.position());
sc.write(r_bBuf);
System.out.println(r_bBuf.position());
r_bBuf.flip();
System.out.println(r_bBuf.asCharBuffer().toString());
r_bBuf.clear();
System.out.println("处理完毕...");
try {
Thread.currentThread().sleep(10000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public abstract int write(ByteBuffer src)
throws IOException
将字节序列从给定的缓冲区中写入此通道。
public abstract int read(ByteBuffer dst)
throws IOException
将字节序列从此通道中读入给定的缓冲区。
[解决办法]
首先 你没有任何关闭操作 如果你说的关闭是把程序关闭...这根本不算关闭连接,这个异常是要做处理的 一方强制关闭 另一方做任何动作必然出现IOException 最好在catch里面关闭掉连接
第二个问题
it.remove();换成key.cancel();两个区别很大,这个问题以前我遇到过 当时调试了很长时间看变量信息发现的问题,现在想不太起来了 反正it.remove()后你那个read操作可以一直在
第三个问题
你这程序只能连接一个客户端,如果连接两个就出问题,你是这样设计的话就无视这个问题
第四个问题
客户端你起码给一个退出的信号吧 全部强制结束?
比如
- Java code
String str = br.readLine(); if(str==null||str.length()==0) { sc.close(); break; }
[解决办法]