JAVA网络编程建立客户端与服务端(BIO)

客户端代码

public class MySocket {
    public static void main(String[] args) {
        try {
            InetAddress localHost = InetAddress.getLocalHost();
            String hostAddress = localHost.getHostAddress();
            System.out.println(hostAddress);
            Socket socket = new Socket(hostAddress, 9090);
            OutputStream outputStream = socket.getOutputStream();
            outputStream.write("1".getBytes("UTF-8"));
            outputStream.flush();
            outputStream.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

服务端代码

public class MyServerSocket {

    public static void main(String[] args) {
        try {
            ServerSocket server = new ServerSocket(9090);
            System.out.println("等待连接");
            Socket socket = server.accept();
            System.out.println("连接创建");
            InputStream inputStream = socket.getInputStream();
            byte[] bytes = new byte[1024];
            int len;
            StringBuilder sb = new StringBuilder();
            while ((len = inputStream.read(bytes)) != -1) {
                sb.append(new String(bytes, 0, len,"UTF-8"));
            }
            System.out.println(sb);
            inputStream.close();
            socket.close();
            server.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

这是通过BIO方式实现对端口的监听,弊端是这样只能接收一个tcp链接,那么我们如果想要使服务端能够接收更多的TCP连接,我们需要在主线程中accept更多的TCP连接拿到连接后,通过启动线程的方式来对单条数据进行读写操作

/**
 * 多线程方式创建server端为了可以监听多个连接每次拿到连接后开启一个新线程单独处理每个连接不阻塞其他的连接到来
 * 无线开辟线程,到达一定数量级存在问题
 */
public class SocketBIOThread {
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(9090);
        System.out.println("Port 9090 has been listening");

        for (; ; ) {
            // 阻塞获等待客户端连接
            Socket client = server.accept();

            new Thread(() -> {
                try (InputStream in = client.getInputStream()) {
                    BufferedReader reader = new BufferedReader(new InputStreamReader(in));
                    while (true) {
                        // 阻塞获取数据
                        String data = reader.readLine();
                        if (null != data) {
                            System.out.println(data);
                        } else {
                            client.close();
                            break;
                        }
                    }
                    System.out.println("连接断开");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();
        }

    }
}

这样可以无限的接收线程,但是弊端是无限开辟线程当TCP连接达到一定数量级之后线程过多,每次对线程的调用会造成用户态内核态的切换,会导致接收数据越来越慢,于是我想到使用线程池来限制连接的个数

/**
 * 使用线程池的方式实现BIO,但是连接的数量有限
 */
public class SocketBIOThreadPool {

    //server socket listen property:
    private static final int RECEIVE_BUFFER = 10;
    private static final int SO_TIMEOUT = 0;
    private static final boolean REUSE_ADDR = false;
    private static final int BACK_LOG = 2;
    //client socket listen property on server endpoint:
    private static final boolean CLI_KEEPALIVE = false;
    private static final boolean CLI_OOB = false;
    private static final int CLI_REC_BUF = 20;
    private static final boolean CLI_REUSE_ADDR = false;
    private static final int CLI_SEND_BUF = 20;
    private static final boolean CLI_LINGER = true;
    private static final int CLI_LINGER_N = 0;
    private static final int CLI_TIMEOUT = 0;
    private static final boolean CLI_NO_DELAY = false;


    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(9090);
        System.out.println("Port 9090 has been listening");
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 1, TimeUnit.MINUTES, new LinkedBlockingDeque<>(10), new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                System.out.println("连接已满");
            }
        });

        while (true){
            Socket client = server.accept();
           /* client.setKeepAlive(true);
            // 设置发送缓冲区大小
            client.setSendBufferSize(10);
            // 设置不优化tcp在buffer中有数据直接发送不等待缓存区存满
            client.setTcpNoDelay(true);*/
            threadPool.execute(()->{
                try (InputStream in = client.getInputStream()) {
                    BufferedReader reader = new BufferedReader(new InputStreamReader(in));
                    client.getOutputStream();
                    while (true) {
                        // 阻塞获取数据
                        String data = reader.readLine();
                        if (null != data) {
                            System.out.println(data);
                        } else {
                            client.close();
                            break;
                        }
                    }
                    System.out.println("连接断开");
                    client.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }
    }
}

这样实现后其实并没有根本的解决问题,这样做只是限制了连接数,但是没有从根本解决问题,所以引出了NIO的方式来建立连接

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值