基于 java nio 长连接实现的聊天室
来源:互联网 发布:阿里云ecs ip 编辑:程序博客网 时间:2024/05/20 20:18
TCP长连接与短连接的区别
基于 java nio 长连接实现的聊天室,如果并发量大的话,可能会有线程问题。
服务端代码
package com.lp.io.socket;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.ArrayList;import java.util.Collections;import java.util.Iterator;import java.util.List;public class LpNioServerSocket { //线程安全 private static List<SocketChannel> channels = Collections.synchronizedList( new ArrayList<SocketChannel>() ); public static void main(String[] args) { HandlerSelectionKey handler = new HandlerHandlerSelectionKeyImpl(); try { //创建 ServerSocketChannel ServerSocketChannel server = ServerSocketChannel.open(); server.configureBlocking(false); server.bind(new InetSocketAddress("localhost", 12345)); //创建 Selector Selector selector = Selector.open(); server.register(selector, SelectionKey.OP_ACCEPT); //死循环,持续接收 客户端连接 while(true) { //selector.select(); 是阻塞方法 int keys = selector.select(); if(keys > 0) { Iterator<SelectionKey> it = selector.selectedKeys().iterator(); while(it.hasNext()) { SelectionKey key = it.next(); it.remove(); //处理 SelectionKey handler.handler(key, selector); } } } } catch (IOException e) { e.printStackTrace(); } } /** * SelectionKey 处理接口 * */ public static interface HandlerSelectionKey { public void handler(SelectionKey key, Selector selector) throws IOException; } /** * SelectionKey 接口 实现类 * */ public static class HandlerHandlerSelectionKeyImpl implements HandlerSelectionKey { @Override public void handler(SelectionKey key, Selector selector) throws IOException { int keyState = selectionKeyState(key); switch (keyState) { case SelectionKey.OP_ACCEPT: ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel(); accept(serverSocketChannel, selector); break; case SelectionKey.OP_READ: SocketChannel readSocketChannel = (SocketChannel) key.channel(); read(readSocketChannel, selector); break; } } /** * 获取 SelectionKey 是什么事件 * @param key * @return */ private int selectionKeyState(SelectionKey key) { if(key.isAcceptable()) { return SelectionKey.OP_ACCEPT; } else if(key.isReadable()) { return SelectionKey.OP_READ; } return -1; } /** * 接口客户端请求 * @param serverSocketChannel * @param selector * @throws IOException */ private void accept(ServerSocketChannel serverSocketChannel, Selector selector) throws IOException { SocketChannel socketChannel = serverSocketChannel.accept(); socketChannel.configureBlocking(false); channels.add(socketChannel); //将 channel 注册到 Selector socketChannel.register(selector, SelectionKey.OP_READ); } /** * 读取客户端发送过来的信息 * @param socketChannel * @param selector * @throws IOException */ private void read(SocketChannel socketChannel, Selector selector) throws IOException { ByteBuffer readBuffer = ByteBuffer.allocate(8192); int readBytes = socketChannel.read(readBuffer); String msg = "";//客户端发送来的消息 if(readBytes > 0) { msg = new String(readBuffer.array(), 0, readBytes); System.out.println("客户端发送来的消息"); System.out.println(msg); } write(socketChannel, msg); } /** * 响应客户端请求 * @param socketChannel * @param selector * @throws IOException */ private void write(SocketChannel socketChannel, String msg) throws IOException { msg = "游客" + socketChannel.hashCode()+ "\r\n " + msg; //响应消息 byte[] responseByte = msg.getBytes(); ByteBuffer writeBuffer = ByteBuffer.allocate(responseByte.length); writeBuffer.put(responseByte); writeBuffer.flip(); //响应客户端 for(int i=0; i<channels.size(); i++) { if(!socketChannel.equals(channels.get(i))) { channels.get(i).write(writeBuffer); } } } }}
客户端代码
package com.lp.io.socket;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.net.Socket;import java.net.UnknownHostException;public class LpSocketClient1 { /** * @param args * @throws IOException * @throws UnknownHostException * @throws InterruptedException */ public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException { final Socket socket = new Socket("localhost", 12345); Thread inT = new Thread(new Runnable() { @Override public void run() { try { while(true) { InputStream inputStream = socket.getInputStream(); byte[] b = new byte[8192]; int readSize = inputStream.read(b); System.out.println(new String(b,0,readSize)); } } catch (IOException e) { e.printStackTrace(); } } }); inT.start(); while(true) { InputStreamReader stdin = new InputStreamReader(System.in);//键盘输入 BufferedReader bufin = new BufferedReader(stdin); String str = bufin.readLine(); System.out.println(str); OutputStream outStream = socket.getOutputStream(); outStream.write(str.getBytes()); outStream.flush(); } }}
启动服务端代码,然后启动多个客户端。在某个客户端代码控制台输入英文(输入中文乱码),点击回车,可以看到其他客户端控制台有信息输出。
0 0
- 基于 java nio 长连接实现的聊天室
- 基于NIO的长连接的实现已开放到github
- java nio实现聊天室功能
- 聊天室(自己实现HTTP长连接)
- 【Java.NIO】NIO的长连接及NIO的内存泄漏
- 基于iframe的HTTP长连接实现
- Java实现长连接
- 基于Java Socket的自定义协议,实现Android与服务器的长连接(一)
- 基于Java Socket的自定义协议,实现Android与服务器的长连接(二)
- 基于Java Socket的自定义协议,实现Android与服务器的长连接(二)
- 基于Java Socket的自定义协议,实现Android与服务器的长连接(一)
- 用java nio写的一个聊天室
- java NIO及NIO聊天室
- Java实现的TCP长连接服务
- TCP长连接服务的Java实现
- TCP长连接服务的Java实现
- Java NIO 聊天室实例
- Java nio 聊天室
- 项目修炼之路(2)测试-TCPCopy
- 使用HttpUrlConnection进行post请求上传文件
- matlab出现Invalid file identifier. Use fopen to generate a valid file identifier错误
- HDU 1242 Rescue (BFS or DFS)
- ionic02-----列表新闻的获取
- 基于 java nio 长连接实现的聊天室
- 知识片段---表判断是处于上划还是下滑
- Android ListView点击展开收起效果(一)
- 南阳oj 题目44 子串和
- android学习笔记之ImageView的scaleType属性
- tickers
- 谈谈Javascript中的异步调用的上下文
- 照片选择器
- 设置字体的行距和大小颜色等