java中socket 和 socketchannel通信

Socket:

代码如下:

ServerSocket serverSocket = new ServerSocket(2000);

while (true) {
Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();// 得到一个输入流,接收客户端传递的信息
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);// 提高效率,将自己字节流转为字符流
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);// 加入缓冲区
CharBuffer charBuffer = CharBuffer.allocate(1024);
while (bufferedReader.read(charBuffer) != -1) {
charBuffer.flip();
char[] inc = new char[charBuffer.limit()];

System.out.println("已接收到客户端连接");

                                charBuffer.get(inc);

System.out.println(Thread.currentThread().getName() + "服务端接收到客户端信息:" +                                                     new String(inc)
+ ",当前客户端ip为:" + socket.getInetAddress().getHostAddress());
charBuffer.clear();
}

}

如果没有客户端连接代码会一直阻塞在Socket socket = serverSocket.accept();,当有客户端连接并发送数据时会执行代码,如果没有数据会阻塞在while (bufferedReader.read(charBuffer) != -1)其他客户端无法连接。如果想要其他客户端和服务端保持长连接需要用多线程。

代码如下:

               ServerSocket serverSocket = new ServerSocket(2000);
while (true) {
Socket socket = serverSocket.accept();
new Thread(new Runnable() {
@Override
public void run() {
InputStream inputStream;
try {
inputStream = socket.getInputStream();
// 得到一个输入流,接收客户端传递的信息
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);// 提高效率,将自己字节流转为字符流
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);// 加入缓冲区
CharBuffer charBuffer = CharBuffer.allocate(1024);
while (bufferedReader.read(charBuffer) != -1) {
charBuffer.flip();
char[] inc = new char[charBuffer.limit()];
System.out.println("已接收到客户端连接");
charBuffer.get(inc);
System.out.println(
 Thread.currentThread().getName() + "服务端接收到客户端信息:" + new                                                                          String(inc)
+ ",当前客户端ip为:" +                                                                                                                                      socket.getInetAddress().getHostAddress());
       charBuffer.clear();
}


} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
;


}

每一个客户端过来,为了保持长连接,服务端都要开启一个线程,这样很浪费资源。

socketchannel:

public void testServer() throws Exception {
ServerSocketChannel server = ServerSocketChannel.open();
Selector selector = Selector.open();
// 开启非阻塞
server.configureBlocking(false);
// 开启监听
server.socket().bind(new InetSocketAddress(2000));
server.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
selector.select();// 当前操作会阻塞,直到至少一个通道被选择
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectedKeys.iterator();
SelectionKey selectionKey = null;
while (iterator.hasNext()) {
selectionKey = iterator.next();
if (selectionKey.isAcceptable()) {
ServerSocketChannel ssc = (ServerSocketChannel) selectionKey.channel();
SocketChannel accept = ssc.accept();
// 设置阻塞
accept.configureBlocking(false);
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
System.out.println(accept.getRemoteAddress()+"客户端连接");
accept.register(selectionKey.selector(), SelectionKey.OP_READ, byteBuffer);
} else if (selectionKey.isReadable()) {
SocketChannel clientChannel = (SocketChannel) selectionKey.channel();
ByteBuffer buffer = (ByteBuffer) selectionKey.attachment();
buffer.clear();
while (clientChannel.read(buffer) > 0) {
buffer.flip();
byte[] as = new byte[buffer.limit()];
buffer.get(as);
System.out.println(Thread.currentThread().getName() + "接收的数据:" + new String(as));
buffer.clear();


}
}
iterator.remove();
}
}


}

         

通过socketChannel 设置非阻塞,并通过选择器,可以用一个线程对个客户端保持长连接,这个通过轮询的方式来处理的。


猜你喜欢

转载自blog.csdn.net/hyhanyu/article/details/80321538
今日推荐