这个demo演示了NIO在客户端并发访问多个站点的示例:
同时访问了 www.kaola.com,www.jd.com,www.tmall.com,www.suning.com这个四个站点的首页,通过打印的信息可以发现总耗时取决于最大suning的耗时。
ue May 09 23:41:07 CST 2017[1494344467724],main,end... Tue May 09 23:41:07 CST 2017[1494344467724],main,connecting to www.kaola.com Tue May 09 23:41:07 CST 2017[1494344467724],main,connecting to www.jd.com Tue May 09 23:41:07 CST 2017[1494344467724],main,connecting to www.suning.com Tue May 09 23:41:07 CST 2017[1494344467725],main,connecting to www.tmall.com Tue May 09 23:41:07 CST 2017[1494344467725],main,running... Tue May 09 23:41:07 CST 2017[1494344467737],main,接收:www.kaola.com的请求耗时:13 Tue May 09 23:41:07 CST 2017[1494344467752],main,接收:www.jd.com的请求耗时:28 Tue May 09 23:41:07 CST 2017[1494344467752],main,接收:www.tmall.com的请求耗时:28 Tue May 09 23:41:07 CST 2017[1494344467781],main,接收:www.suning.com的请求耗时:57 56
/** * Desc:TODO * * @author wei.zw * @since 2017年5月9日 下午7:31:20 * @version v 0.1 */ public class HttpSocket { private Selector selector; private final Map<String, Long> startTimeMap = new HashMap<>(); /** * @param host * @param port */ public HttpSocket() { super(); try { selector = Selector.open(); } catch (Exception e) { e.printStackTrace(); System.exit(1); } } /** * * * @author wei.zw */ public void start() { LogUitl.log("running..."); long start = System.currentTimeMillis(); while (startTimeMap.size() > 0) { try { selector.select(1); Set<SelectionKey> selectionKeys = selector.selectedKeys(); Iterator<SelectionKey> it = selectionKeys.iterator(); SelectionKey key = null; while (it.hasNext()) { key = it.next(); it.remove(); try { handleInput(key); } catch (Exception e) { if (key != null) { key.cancel(); if (key.channel() != null) { key.channel().close(); } } } } } catch (IOException e) { System.exit(1); } } System.out.println(System.currentTimeMillis() - start); // end if (selector != null) { try { LogUitl.log("close"); selector.close(); } catch (IOException e) { e.printStackTrace(); System.exit(1); } } LogUitl.log("end..."); } /** * 处理输入 * @param key * @author wei.zw * @throws IOException */ private void handleInput(SelectionKey key) throws IOException { if (key.isValid()) { SocketChannel sc = (SocketChannel) key.channel(); if (key.isConnectable()) { if (sc.finishConnect()) { String str = sc.getRemoteAddress().toString(); String host = str.substring(0, str.indexOf("/")); doWrite(sc, host); } else { System.exit(1); } } if (key.isReadable()) { String str = sc.getRemoteAddress().toString(); String host = str.substring(0, str.indexOf("/")); if (!startTimeMap.containsKey(host)) { return; } ByteBuffer readBuffer = ByteBuffer.allocate(1024); int readBytes = sc.read(readBuffer); if (readBytes > 0) { readBuffer.flip(); byte[] bytes = new byte[readBuffer.remaining()]; readBuffer.get(bytes); readBuffer.clear(); // String body = new String(bytes, "UTF-8"); // System.out.println(body); LogUitl.log("接收:" + host + "的请求耗时:" + (System.currentTimeMillis() - startTimeMap.get(host))); startTimeMap.remove(host); // stop--; } else if (readBytes < 0) { key.cancel(); sc.close(); } } } } /** * 创建SocketChannel 向Selector注册SocketChannel 链接channel的socket * * @author wei.zw * @throws IOException */ public void doHttpConnection(String host, int port) throws IOException { SocketChannel socketChannel = SocketChannel.open(); socketChannel.configureBlocking(false); startTimeMap.put(host, System.currentTimeMillis()); LogUitl.log("connecting to " + host); socketChannel.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ); socketChannel.connect(new InetSocketAddress(InetAddress.getByName(host), port)); } /** * * @param socketChannel2 * @author wei.zw * @throws IOException */ private void doWrite(SocketChannel socketChannel, String host) throws IOException { StringBuilder sb = new StringBuilder().append("GET / HTTP/1.1\r\n").append("Host: " + host + " \r\n") .append("\r\n"); byte[] req = sb.toString().getBytes(); ByteBuffer writeBuffer = ByteBuffer.allocate(req.length); writeBuffer.put(req); writeBuffer.flip(); socketChannel.write(writeBuffer); if (!writeBuffer.hasRemaining()) { } } }
相关推荐
- 为了提高搜索效率,搜索引擎可能使用多线程技术,同时处理多个FTP连接或搜索任务。 - `java.util.concurrent`包提供了一系列工具类,如`ExecutorService`,便于管理和调度并发任务。 8. **性能优化**: - 为...
xSocket是一个轻量级的基于nio的服务器框架用于开发高性能、可扩展、多线程的服务器。该框架封装了线程处理、异步读/写等方面。 Java多线程程序死锁检查 JCarder JCarder 是一个用来查找多线程应用程序中一些潜在的...
4. **服务器架构**:服务器端可能采用多线程或多进程处理客户端请求,也可能使用事件驱动或异步I/O模型(如Node.js的Event Loop或Java的NIO)来提高并发性能。 5. **信号控制**:视频聊天系统需要实现信令机制,...
xSocket是一个轻量级的基于nio的服务器框架用于开发高性能、可扩展、多线程的服务器。该框架封装了线程处理、异步读/写等方面。 Java多线程程序死锁检查 JCarder JCarder 是一个用来查找多线程应用程序中一些潜在的...
xSocket是一个轻量级的基于nio的服务器框架用于开发高性能、可扩展、多线程的服务器。该框架封装了线程处理、异步读/写等方面。 Java多线程程序死锁检查 JCarder JCarder 是一个用来查找多线程应用程序中一些潜在的...
xSocket是一个轻量级的基于nio的服务器框架用于开发高性能、可扩展、多线程的服务器。该框架封装了线程处理、异步读/写等方面。 Java多线程程序死锁检查 JCarder JCarder 是一个用来查找多线程应用程序中一些潜在的...
xSocket是一个轻量级的基于nio的服务器框架用于开发高性能、可扩展、多线程的服务器。该框架封装了线程处理、异步读/写等方面。 Java多线程程序死锁检查 JCarder JCarder 是一个用来查找多线程应用程序中一些潜在的...
xSocket是一个轻量级的基于nio的服务器框架用于开发高性能、可扩展、多线程的服务器。该框架封装了线程处理、异步读/写等方面。 Java多线程程序死锁检查 JCarder JCarder 是一个用来查找多线程应用程序中一些潜在的...
xSocket是一个轻量级的基于nio的服务器框架用于开发高性能、可扩展、多线程的服务器。该框架封装了线程处理、异步读/写等方面。 Java多线程程序死锁检查 JCarder JCarder 是一个用来查找多线程应用程序中一些潜在的...
xSocket是一个轻量级的基于nio的服务器框架用于开发高性能、可扩展、多线程的服务器。该框架封装了线程处理、异步读/写等方面。 Java多线程程序死锁检查 JCarder JCarder 是一个用来查找多线程应用程序中一些潜在的...
xSocket是一个轻量级的基于nio的服务器框架用于开发高性能、可扩展、多线程的服务器。该框架封装了线程处理、异步读/写等方面。 Java多线程程序死锁检查 JCarder JCarder 是一个用来查找多线程应用程序中一些潜在的...
xSocket是一个轻量级的基于nio的服务器框架用于开发高性能、可扩展、多线程的服务器。该框架封装了线程处理、异步读/写等方面。 Java多线程程序死锁检查 JCarder JCarder 是一个用来查找多线程应用程序中一些潜在的...
xSocket是一个轻量级的基于nio的服务器框架用于开发高性能、可扩展、多线程的服务器。该框架封装了线程处理、异步读/写等方面。 Java多线程程序死锁检查 JCarder JCarder 是一个用来查找多线程应用程序中一些潜在的...
xSocket是一个轻量级的基于nio的服务器框架用于开发高性能、可扩展、多线程的服务器。该框架封装了线程处理、异步读/写等方面。 Java多线程程序死锁检查 JCarder JCarder 是一个用来查找多线程应用程序中一些潜在的...
xSocket是一个轻量级的基于nio的服务器框架用于开发高性能、可扩展、多线程的服务器。该框架封装了线程处理、异步读/写等方面。 Java多线程程序死锁检查 JCarder JCarder 是一个用来查找多线程应用程序中一些潜在的...
- **Common, Server, Shared Libraries**:这些目录用于存放可以被多个Web应用共享的JAR文件,不同目录代表加载的时机不同。 此外,Tomcat 7.0.26版本还支持以下特性: - **JSP 2.2** 和 **Servlet 3.0** 规范,...
8. **虚拟主机(Virtual Hosts)**:通过配置`server.xml`中的`<Host>`元素,可以在同一台Tomcat服务器上部署多个独立的Web站点。 9. **热部署**:当Web应用的类或资源发生改变时,Tomcat可以自动检测并重新加载,...
每个客户端连接都会被分配一个独立的线程来处理,确保服务器可以并发地响应多个请求。 4. **FTP协议**:FTP协议包括一系列的命令和响应,如USER(用户认证)、PASS(密码认证)、LIST(列出目录内容)、RETR(下载...
- **`Selector`**:用于监控多个通道的就绪状态。 - **`Channel`**:用于读写数据的通道。 #### 二十七、非阻塞I/O的缓冲区 `Buffer`类用于存储和操作数据。 - **常用方法**:`flip()`、`clear()`、`compact()`等...