Java Socket学习---nio实现阻塞多线程通信
2015-10-10 19:31
609 查看
本次使用nio实现socket客户端和服务端的通信,并且在服务端为每一个新建的连接创建一个线程负责维持和客户端的通信。
使用nio实现的阻塞的socket与普通方式实现的通信相比较仅仅是实现方式不同,其实质的运行原理是一样的。在此仅仅作为一个nio的入门示例。
nio来做socket主要用到两个类ServerSocketChannel(服务器socket)和SocketChannel(客户端socket)。
Channel的简单介绍:ServerSocketChannel和SocketChannel。Java NIO的通道类似流,但又有些不同:
1. 既可以从通道中读取数据,又可以写数据到通道。但流的读写通常是单向的。
2. 通道可以异步地读写。
3. 通道中的数据总是要先读到一个Buffer,或者总是要从一个Buffer中写入。
Server端程序:
Client端程序:
SocketUtils:(与以前的一样)
使用nio实现的阻塞的socket与普通方式实现的通信相比较仅仅是实现方式不同,其实质的运行原理是一样的。在此仅仅作为一个nio的入门示例。
nio来做socket主要用到两个类ServerSocketChannel(服务器socket)和SocketChannel(客户端socket)。
Channel的简单介绍:ServerSocketChannel和SocketChannel。Java NIO的通道类似流,但又有些不同:
1. 既可以从通道中读取数据,又可以写数据到通道。但流的读写通常是单向的。
2. 通道可以异步地读写。
3. 通道中的数据总是要先读到一个Buffer,或者总是要从一个Buffer中写入。
Server端程序:
package com.henushang.socket.chapter4nio; import java.io.BufferedReader; import java.io.IOException; import java.io.PrintWriter; import java.net.InetSocketAddress; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import com.henushang.socket.util.SocketUtils; public class EchoServer { private int port = 8000; private ServerSocketChannel serverSocketChannel; private ExecutorService executorService; private final int POOL_SIZE = 4; public EchoServer() throws Exception { executorService = Executors.newFixedThreadPool(Runtime.getRuntime() .availableProcessors() * POOL_SIZE); serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.socket().bind(new InetSocketAddress(port)); System.out.println("等待连接..."); } public void service() { SocketChannel socketChannel = null; while (true) { try { System.out.println("waitting for connect..."); socketChannel = serverSocketChannel.accept(); System.out.println("get the connect..."); Thread.sleep(500); executorService.execute(new Handler(socketChannel)); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) throws Exception { new EchoServer().service(); } class Handler implements Runnable { private SocketChannel socketChannel = null; public Handler(SocketChannel socketChannel) { this.socketChannel = socketChannel; } @Override public void run() { handler(socketChannel); } private void handler(SocketChannel socketChannel) { System.out.println("new connection accepted:" + socketChannel.socket().getInetAddress() + ":" + socketChannel.socket().getPort()); try { BufferedReader reader = SocketUtils .getReader(this.socketChannel); PrintWriter pw = SocketUtils.getWriter(this.socketChannel); String msg = null; while (true) { if ((msg = reader.readLine()) != null) { try { Thread.sleep(20000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(msg); // pw.write(SocketUtils.echo(msg)+"\r\n"); pw.println(SocketUtils.echo(msg)); pw.flush(); if ("bye".equals(msg)) { break; } } } } catch (IOException e) { e.printStackTrace(); } finally { SocketUtils.close(socketChannel); } } } }
Client端程序:
package com.henushang.socket.chapter4nio; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.InetAddress; import java.net.InetSocketAddress; import java.nio.channels.SocketChannel; import com.henushang.socket.util.SocketUtils; public class EchoClient { private SocketChannel socketChannel; private int port = 8000; public EchoClient() throws Exception { socketChannel = SocketChannel.open(); InetAddress inetAddress = InetAddress.getLocalHost(); InetSocketAddress inetSocketAddress = new InetSocketAddress(inetAddress, port); socketChannel.connect(inetSocketAddress); System.out.println("准备连接服务器"); } public static void main(String[] args) throws Exception { new EchoClient().talk(); } public void talk() { try { BufferedReader reader = SocketUtils.getReader(socketChannel.socket()); PrintWriter pw = SocketUtils.getWriter(socketChannel.socket()); BufferedReader localreaderReader = new BufferedReader(new InputStreamReader(System.in)); String msg = null; while ((msg = localreaderReader.readLine()) != null) { System.out.println(msg); pw.println(msg); pw.flush(); System.out.println(reader.readLine()); if ("bye".equals(msg)) { break; } } } catch (IOException e) { e.printStackTrace(); }finally{ SocketUtils.close(socketChannel); } } }
SocketUtils:(与以前的一样)
package com.henushang.socket.util; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.Socket; import java.nio.channels.SocketChannel; public class SocketUtils { public static PrintWriter getWriter(Socket socket) throws IOException { OutputStream os = socket.getOutputStream(); return new PrintWriter(os); } public static PrintWriter getWriter(SocketChannel socketChannel) throws IOException { return getWriter(socketChannel.socket()); } public static BufferedReader getReader(Socket socket) throws IOException{ InputStream is = socket.getInputStream(); return new BufferedReader(new InputStreamReader(is, "UTF-8")); } public static BufferedReader getReader(SocketChannel socketChannel) throws IOException{ return getReader(socketChannel.socket()); } public static void close(Socket socket) { try { if (socket != null) { socket.close(); } } catch (Exception e) { e.printStackTrace(); } } public static void close(SocketChannel socketChannel) { try { if (socketChannel != null) { socketChannel.close(); } } catch (Exception e) { e.printStackTrace(); } } public static String echo(String msg) { return "echo:" + msg; } }
相关文章推荐
- Java基础篇-集合
- Spring Boot实践应用开发(6)
- java动态代理(JDK和cglib)
- spring二级缓存的ehcache 的 配置文件
- Java设计模式——开篇
- java反射机制详解 及 Method.invoke解释
- Codeforces - 546C. Soldier and Cards- Java题解
- Java没有源代码的同步集合~
- Netbeans中的一些小知识
- spring transaction 注解方法报错Can not set field to proxy
- discuz社区与java web的钉钉手机版整合(二)
- Java Json Html ajax数据传递
- 【解决】kettle启动时出现的Java Runtime Environment异常
- MyEclipse创建HelloWeb
- Java关键字final、static使用总结
- eclipse反编译插件
- java7 NIO2 watching service API
- Swagger与SpringMVC的整合
- Spring学习笔记(十):@Autowired和new的区别
- Java单例设计模式