java模拟服务器客户端通讯(nio,聊天)

服务器:

import util.MsgSendUtil;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * 服务端
 * @author gaokuo
 **/
public class ProductService {

    public static void main(String[] args) throws IOException {
        MsgSendUtil msgSendUtil = new MsgSendUtil();
        //收集待发送消息
        new Thread(msgSendUtil::inp).start();
        //发送消息
        new Thread(msgSendUtil::send).start();
        //监听端口
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //切换非阻塞
        serverSocketChannel.configureBlocking(false);
        //绑定端口
        serverSocketChannel.bind(new InetSocketAddress("localhost",9696));
        //注册选择器
        Selector selector = Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        while (selector.select() > 0){
            Set selectionKeys = selector.selectedKeys();
            Iterator iterator = selectionKeys.iterator();
            while(iterator.hasNext()){
                SelectionKey selectionKey = iterator.next();
                if(selectionKey.isAcceptable()){
                    //客户端已完成连接
                    MsgSendUtil.client = serverSocketChannel.accept();
                    //切换成非阻塞状态
                    MsgSendUtil.client.configureBlocking(false);
                    //注册到选择器上 监听读就绪事件
                    MsgSendUtil.client.register(selector, SelectionKey.OP_READ);
                }else if(selectionKey.isReadable()){
                    //有读事件,读取就绪的信息
                    MsgSendUtil.read(selectionKey);
                }
                //删除已处理事件
                iterator.remove();
            }
        }
    }

}

客户端:

import util.MsgSendUtil;

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.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * 客户端
 * @author gaokuo
 **/
public class ProductCustomer {

    public static void main(String[] args) throws IOException {
        MsgSendUtil msgSendUtil = new MsgSendUtil();
        //收集待发送消息
        new Thread(msgSendUtil::inp).start();
        //发送消息
        new Thread(msgSendUtil::send).start();
        //连接端口
        MsgSendUtil.client = SocketChannel.open(new InetSocketAddress("localhost",9696));
        //默认为阻塞,切换为非阻塞模式
        MsgSendUtil.client.configureBlocking(false);
        //发送信息给服务端
        String msg = "连接已经建立!";
        //创建数据缓存区
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        byteBuffer.put(msg.getBytes());
        byteBuffer.flip();
        MsgSendUtil.client.write(byteBuffer);
        Selector selector = Selector.open();
        MsgSendUtil.client.register(selector, SelectionKey.OP_READ);
        while (selector.select() > 0){
            Set selectionKeys = selector.selectedKeys();
            Iterator iterator = selectionKeys.iterator();
            while(iterator.hasNext()){
                SelectionKey selectionKey = iterator.next();
                if(selectionKey.isReadable()){
                    //有读事件,读取就绪的信息
                    MsgSendUtil.read(selectionKey);
                }
                //删除已处理事件
                iterator.remove();
            }
        }
    }

}

工具类:

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 通讯工具
 * @author gaokuo
 **/
public class MsgSendUtil {

    /**
     * 控制台输入收集
     */
    private static Scanner scan = new Scanner(System.in);
    /**
     * 待发送消息列表
     */
    private static List bufferList = Collections.synchronizedList(new ArrayList<>(4));
    /**
     * 连接
     */
    public static SocketChannel client;
    private static SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");

    /**
     * 控制台输入
     */
    public void inp(){
        while (true){
            String msg = scan.nextLine();
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            buffer.put(msg.getBytes());
            buffer.flip();
            bufferList.add(buffer);
        }
    }

    /**
     * 数据发送
     */
    public void send() {
        while (true){
            if(bufferList.size() > 0){
                ByteBuffer buffer = bufferList.get(0);
                try {
                    if(client != null){
                        client.write(buffer);
                        bufferList.remove(0);
                    }else{
                        Thread.sleep(5000);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 读取已完成的读就绪时间传送的信息
     * @param selectionKey 就绪读事件对应选择键
     * @throws IOException e
     */
    public static void read(SelectionKey selectionKey) throws IOException {
        SocketChannel client = (SocketChannel) selectionKey.channel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        while (client.read(buffer) > 0){
            buffer.flip();
            byte[] bytes = new byte[buffer.limit()];
            buffer.get(bytes);
            System.out.print(sdf.format(new Date()) + " 接收消息:" + new String(bytes));
        }
        System.out.println();
    }
}

先启动service,再启动customer,控制台输入即可通讯.
服务器控制台打印:

10:24:11 接收消息:连接已经建立!
客户端你吃饭了吗?
10:24:35 接收消息:我吃了,服务器你得劲不?
老得劲了,一顿能吃好多!
10:25:01 接收消息:多吃是福啊哈哈哈哈哈

客户端控制台打印:

10:24:26 接收消息:客户端你吃饭了吗?
我吃了,服务器你得劲不?
10:24:41 接收消息:老得劲了,一顿能吃好多!
多吃是福啊哈哈哈哈哈

你可能感兴趣的:(java)