2021-08-23

java使用nio实现的socket,客户端发送固定的数据,服务端端参生了乱码

客户端:

package com.unimas.rabbitmq1.niosocketOne;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

public class NioClient {
    private static final ExecutorService executor = Executors.newCachedThreadPool();
    private static final AtomicLong countSend=new AtomicLong(0L);
    public static void main(String[] args) throws InterruptedException {
        clientStart();
    }
    public static void clientStart() throws InterruptedException {
        OnlyNosClients();
    }

    private static void OnlyNosClients() throws InterruptedException {
        for (int i = 0; i < 1; i++) {
            executor.submit(
                    new RequestRemoteServerWithTcp("localhost",15004,countSend)
            );

            /*RequestRemoteServerWithTcp tcp  =  new RequestRemoteServerWithTcp("localhost",17899,countSend);
            Thread thread = new Thread(tcp);
            thread.start();*/
        }
        /*//10秒钟后中断所有线程
        TimeUnit.SECONDS.sleep(10);
        executor.shutdownNow();*/
    }

    private static void startNewClients()  {
        while (!Thread.currentThread().isInterrupted())
        {
            executor.submit(
                    new RequestRemoteServerWithTcp("localhost",17899,countSend)
            );
        }
    }
}
package com.unimas.rabbitmq1.niosocketOne;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

public class RequestRemoteServerWithTcp implements Runnable {
    public static  final Logger logger = LoggerFactory.getLogger(RequestRemoteServerWithTcp.class);
    public static  final Locale locale=Locale.SIMPLIFIED_CHINESE;
    private final String serverAddress;
    private final int serverPoint;
    private int localPoint;
    private final AtomicLong countSend ;
    public RequestRemoteServerWithTcp(String serverAddress,int serverPoint,AtomicLong countSend){
        this.serverAddress=serverAddress;
        this.serverPoint=serverPoint;
        this.countSend=countSend;
    }
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see Thread#run()
     */
    @Override
    public void run() {
        try {
            this.doRequest();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
    }
    private void doRequest() throws IOException {
        SocketChannel socketChannel = null;
        try {
            socketChannel = SocketChannel.open(new InetSocketAddress(this.serverAddress,this.serverPoint));
            socketChannel.configureBlocking(false);
            SocketAddress localAddress = socketChannel.getLocalAddress();
            while(!socketChannel.isConnected()){
                System.out.println("ssss");
            }
            logger.debug("[{}]完成连接",socketChannel.getLocalAddress());
            this.localPoint = ((InetSocketAddress) socketChannel.getLocalAddress()).getPort();
            /*while (!Thread.currentThread().isInterrupted())
            {
                ByteBuffer buffer = this.prepareData(this.localPoint);
                socketChannel.write(buffer);
                buffer.clear();
                long currentSendCount = this.countSend.incrementAndGet();
                logger.info("客户端[{}]的第【{}】条数据发送完成",localAddress,currentSendCount);
//                logger.info("客户端[{}]的第【{}】条数据发送完成",Thread.currentThread().getName(),currentSendCount);
//                TimeUnit.SECONDS.sleep(3);
//                ByteBuffer readBuffer = ByteBuffer.allocate(2*1024);
//                getResponseData(socketChannel, readBuffer);
            }*/

            for (int i = 0; i < 10000000; i++) {

                long currentSendCount = this.countSend.incrementAndGet();
                ByteBuffer buffer = this.prepareData(this.localPoint, currentSendCount);
                socketChannel.write(buffer);
                buffer.clear();
//                logger.info("客户端[{}]的第【{}】条数据发送完成",localAddress,currentSendCount);
//                logger.info("客户端[{}]的第【{}】条数据发送完成",Thread.currentThread().getName(),currentSendCount);
//                TimeUnit.SECONDS.sleep(3);
//                ByteBuffer readBuffer = ByteBuffer.allocate(2*1024);
//                getResponseData(socketChannel, readBuffer);
            }
        } catch (IOException ioException) {
            logger.error("ioException:",ioException);
        }catch (Exception e)
        {
            logger.error("端口为{}的客户端报错",this.localPoint,e);
        }finally {
            if (!Objects.isNull(socketChannel)&&socketChannel.isOpen())
            {
                //关闭输出通道
                socketChannel.shutdownOutput();
                socketChannel.shutdownInput();
                socketChannel.close();
                logger.info("【{}】的输出通道关闭!",this.localPoint);
            }
        }

    }

    private void getResponseData(SocketChannel socketChannel, ByteBuffer readBuffer) throws IOException {
        //接收客户端数据
        int readBytes = 0;
        StringBuilder content = new StringBuilder();
        while ((readBytes=socketChannel.read(readBuffer))>0) {
            //处理数据
            content.append(new String(readBuffer.array(), StandardCharsets.UTF_8));
            readBuffer.clear();
        }
        //判断服务端断开连接
        //当服务端没有断开连接的时候readBytes=0这样保持长连接
        //当服务端断开连接的时候readBytes=-1
        if (readBytes<0)
        {
            logger.debug("服务端断开连接.....");
            socketChannel.close();
        }
        //处理数据
        else {
            logger.info("收到的内容是: <{}>",
                    content.toString());
        }
    }

    private ByteBuffer prepareData(int channelPoint, long i)  {
        StringBuilder name =new StringBuilder("hbase代码的迁移:问题打开idea cpu过高,比较卡,重启电脑前两个磁盘都剩余8-9G,重启了一下C盘就剩1个G了hbase代码的迁移:问题打开idea cpu过高,比较卡,重启电脑前两个磁盘都剩余8-9G,重启了一下C盘就剩1个G了hbase代码的迁移:问题打开idea cpu过高,比较卡,重启电脑前两个磁盘都剩余8-9G,重启了一下C盘就剩1个G了hbase代码的迁移:问题打开idea cpu过高,比较卡,重启电脑前两个磁盘都剩余8-9G,重启了一下C盘就剩1个G了hbase代码的迁移:问题打开idea cpu过高,比较卡,重启电脑前两个磁盘都剩余8-9G,重启了一下C盘就剩1个G了hbase代码的迁移:问题打开idea cpu过高,比较卡,重启电脑前两个磁盘都剩余8-9G,重启了一下C盘就剩1个G了hbase代码的迁移:问题打开idea cpu过高,比较卡,重启电脑前两个磁盘都剩余8-9G,重启了一下C盘就剩1个G了hbase代码的迁移:问题打开idea cpu过高,比较卡,重启电脑前两个磁盘都剩余8-9G,重启了一下C盘就剩1个G了hbase代码的迁移:问题打开idea cpu过高,比较卡,重启电脑前两个磁盘都剩余8-9G,重启了一下C盘就剩1个G了hbase代码的迁移:问题打开idea cpu过高,比较卡,重启电脑前两个磁盘都剩余8-9G,重启了一下C盘就剩1个G了重启了一下C盘就剩1个G了hbase代码的迁移:问题打开idea cpu过高,比较卡,重启电脑前两个磁盘都剩余8-9G,重启了一下C盘就剩1个G了hbase代码的迁移:问题打开idea cpu过高,比较卡,重启电脑前两个磁盘都剩余8-9G,重启了一下C盘就剩1个G了hbase代码的迁移:问题打开idea cpu过高,比较卡,重启电脑前两个磁盘都剩余8-9G,重启了一下C盘就剩1个G了问题打开idea cpu过高,比较卡,重启电脑前两个磁盘都剩余8-9G,重启了一下C盘就剩1个G了hbase代码的迁移:问题打开idea cpu过高,比较卡,重启电脑前两个磁盘都剩重启电脑前两个磁盘都剩"+i);
//        StringBuilder name =new StringBuilder("hbase代码的迁移");
        byte[] bytes = name.toString().getBytes(StandardCharsets.UTF_8);
        ByteBuffer byteBuffer = ByteBuffer.allocate(bytes.length+4);
        byteBuffer.putInt(bytes.length);
        byteBuffer.put(bytes);
        byteBuffer.flip();
        return byteBuffer;
//        return ByteBuffer.wrap(name.toString().getBytes(StandardCharsets.UTF_8));
    }
}

服务端:

package com.unimas.rabbitmq1.niosocketOne;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class NioServer {
    public static final Logger logger = LoggerFactory.getLogger(NioServer.class);
    private static final Long TIME_OUT = 3000L;
    private static final BlockingQueue<Future<String>> futureQueue = new LinkedBlockingQueue<>();
    private static final AtomicInteger selectorNos = new AtomicInteger(0);
    private static final AtomicInteger handleDataNo = new AtomicInteger(0);
    private static final AtomicInteger resDataNo = new AtomicInteger(0);

    public static void main(String[] args) throws IOException, InterruptedException {
        startServer(args);
    }

    public static void startServer(String[] args) throws IOException, InterruptedException {
        //新建channel
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //设置服务端属性,为非阻塞模式
        serverSocketChannel.configureBlocking(false);
        //绑定服务端端口
        serverSocketChannel.bind(new InetSocketAddress(15004));
        //新建selector
        Selector selector = Selector.open();
        //注册channel到selector
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        logger.debug("服务在[{}]启动成功,正在监听事件。。。。。", serverSocketChannel.getLocalAddress());
        //while循环监听事件
        while (!Thread.currentThread().isInterrupted()) {
//            if (selector.select(TIME_OUT) > 0) {
            if (selector.select() > 0) {
                /*logger.warn("第【{}】轮监听===============================================",
                        selectorNos.incrementAndGet());*/
                //获取事件类型
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                //selector监听到的ready事件集
                Iterator<SelectionKey> readyKeys = selectionKeys.iterator();
                //处理事件
                while (readyKeys.hasNext()) {
                    SelectionKey key = readyKeys.next();
                    //移除channel事件
                    readyKeys.remove();
                    SocketChannel socketChannel = null;
                    try {
                        //连接
                        if (key.isValid() && key.isAcceptable()) {
                            socketChannel = ((ServerSocketChannel) key.channel()).accept();
                            socketChannel.configureBlocking(false);
                            logger.info("Accept  收到了来自于【{}】的连接请求", socketChannel.getRemoteAddress());
                            //将客户端的可读事件注册到selector中监听
                            socketChannel.register(key.selector(), SelectionKey.OP_READ|SelectionKey.OP_WRITE);
                        }
                        //数据可读
                        if (key.isValid() && key.isReadable()) {
                            socketChannel = (SocketChannel) key.channel();
//                            logger.info("Readable   客户端【{}】准备好了数据  ", socketChannel.getRemoteAddress());
                            getRequestData(key);
                        }
                        /*if (key.isValid() && key.isWritable()) {
                            logger.info("Readable   服务端【{}】准备写入数据 ");
                            doResponse(key);

                        }*/
                    } catch (IOException ioException) {
                        logger.error("服务端IO异常:\n", ioException.getCause());
                        if (!Objects.isNull(socketChannel)) {
                            socketChannel.close();
                            key.cancel();
                        }
                    }
                }
            }
        }
        //关闭channel
        serverSocketChannel.close();
        selector.close();
        logger.info("进程退出");
    }

    //处理连接请求
    private static void getRequestData(SelectionKey selectionKey) throws IOException {
        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
        //写入数据到buffer
        try {
            if (socketChannel.isOpen()) {
                socketChannel.socket().setReceiveBufferSize(209715200);
                //将写事件注册到selector
//                socketChannel.register(selectionKey.selector(), selectionKey.interestOps()|SelectionKey.OP_WRITE);
                //准备buffer
                ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4);
                // 首先读取消息头(自己设计的协议头,此处是消息体的长度)
                int headCount = socketChannel.read(byteBuffer);
                if (headCount < 0) {
                    return;
                }
                byteBuffer.clear();
//                byteBuffer.flip();
                int length = byteBuffer.getInt();
                // 读取消息体
//                logger.info(length+"  " + handleDataNo.incrementAndGet());
                byteBuffer = ByteBuffer.allocate(length);
                int bodyCount = socketChannel.read(byteBuffer);
                if (bodyCount > 0) {
                    /*logger.info("第【{}】次处理数据,收到的内容是: {}", handleDataNo.incrementAndGet(),
                            new String(byteBuffer.array(),"UTF-8"));*/
                String ss=    byteBuffer.toString();
                    /*logger.info("第【{}】次处理数据,收到的内容是: {}", handleDataNo.incrementAndGet(),
                            new String(byteBuffer.array(),"UTF-8"));*/
                    handleDataNo.incrementAndGet();
                }
                byteBuffer.clear();
//                System.gc();

            } else {
                logger.warn("channel 已经关闭!");
                socketChannel.shutdownInput();
                socketChannel.shutdownOutput();
                socketChannel.close();
                selectionKey.cancel();
            }
        } catch (Exception e) {
            logger.error("客户端【{}】错误:", socketChannel, e.getCause());
            e.printStackTrace();
            //关闭连接
            socketChannel.shutdownInput();
            socketChannel.shutdownOutput();
            //将channel从selector中删除
            selectionKey.cancel();
            logger.info("socketChannel【{}】已经从selector取消注册", socketChannel.getRemoteAddress());
            socketChannel.close();
        }
    }

    //返回响应数据
    private static void doResponse(SelectionKey selectionKey) throws IOException {
        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
        String resData = resDataNo.incrementAndGet() + "=========>";
        logger.debug("响应数据[{}]到【{}】", resData, socketChannel.getRemoteAddress());
        socketChannel.write(ByteBuffer.wrap(resData.getBytes()));
    }
}

产生的问题:

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值