【Java】BIO,NIO,AIO聊天室示例

BIO,NIO,AIO聊天室示例

几个概念

  • 同步: 发送方发送请求之后,需要等接收方发回响应后才接着发
  • 异步: 发送方发送请求之后,不等待接收方响应,继续发送下一个,系统内核完成请求后主动通知
  • 阻塞: 在调用结果返回之前,当前线程会被挂起,需等到得到结果后才会返回。线程在此过程中不进行任何其他处理。
  • 非阻塞: 调用结果不会立即返回,当前线程也不会被挂起,而是立即返回执行下一个调用。

socket连接


连接过程:

服务器端:

  1. 创建socket,绑定端口
  2. 开始监听
  3. 等待并接收客户端连接请求,返回新socket
  4. 由新socket与客户端进行交互
  5. 关闭连接

客户端:

  1. 创建socket
  2. 连接服务器与io交互
  3. 关闭连接

示例代码:

服务器端:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

public class ChatServer {

    /**
     * 监听端口号
     */
    private int port = 8081;

    public ChatServer() {
    }

    public ChatServer(int port) {
        this.port = port;
    }

    public void service() {
        try {
            System.out.println("服务器开始建立连接");
            // 建立服务器连接
            ServerSocket serverSocket = new ServerSocket(port);
            System.out.println("服务器开始监听");
            // 开始监听
            Socket socket = serverSocket.accept();
            // 获取输出流,向客户端发送信息
            OutputStream outputStream = socket.getOutputStream();
            BufferedReader reader = null;
            try {
                // 获取输入流,读取客户端传过来的信息
                reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String line = "";
                while ((line = reader.readLine()) != null) {
                    System.out.println("从客户端接收到一条消息,内容为:" + line);
                }
                // 发送消息给客户端
                outputStream.write("我接收到了".getBytes(StandardCharsets.UTF_8));
            } finally {
                // 关闭流和连接
                if(reader != null) {
                    reader.close();
                }
                if(outputStream != null) {
                    outputStream.close();
                }
                if(socket != null) {
                    socket.close();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        ChatServer chatServer = new ChatServer();
        chatServer.service();
    }
}

客户端:

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

public class ChatClient {

    private int port = 8080;

    public ChatClient() {
    }

    public ChatClient(int port) {
        this.port = port;
    }

    private void consumer() {
        System.out.println("客户端开始发送数据");
        try {
            Socket client = new Socket("localhost", 8081);
            OutputStream outputStream = client.getOutputStream();
            try {
                outputStream.write("这里是8080端口".getBytes(StandardCharsets.UTF_8));
            } finally {
                if(outputStream != null) {
                    outputStream.close();
                }
                if(client != null) {
                    client.close();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        ChatClient client = new ChatClient();
        client.consumer();
    }
}

运行结果:
在这里插入图片描述

在这里插入图片描述

BIO(同步阻塞IO模式)

每一个客户端的请求都需要服务端开启一个线程处理。

package com.alone.study.chat.bio;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;

import static java.util.concurrent.Executors.newFixedThreadPool;

public class ChatServer {

    /**
     * 监听端口号
     */
    private int port = 8081;
    /**
     * 处理socket的线程池
     */
    private static final ExecutorService EXECUTOR_SERVICE = newFixedThreadPool(10);
    private List<Socket> sockets = new ArrayList<>(10);

    public ChatServer() {
    }

    public ChatServer(int port) {
        this.port = port;
    }

    public void service() {
        try {
            System.out.println("服务器开始建立连接");
            // 建立服务器连接
            ServerSocket serverSocket = new ServerSocket(port);
            System.out.println("服务器开始监听");
            // 开始监听
            Socket socket = serverSocket.accept();
            sockets.add(socket);
            EXECUTOR_SERVICE.submit(new SocketThread(socket));
            Thread.sleep(2000);
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        } finally {
            if(sockets != null) {
                for (Socket socket : sockets) {
                    if(socket != null) {
                        try {
                            socket.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        ChatServer chatServer = new ChatServer();
        chatServer.service();
    }

    private class SocketThread implements Runnable {

        private Socket socket;

        public SocketThread() {
        }

        public SocketThread(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            System.out.println("开始处理来自" + socket.getRemoteSocketAddress() + "的请求");
            // 接收客户端的消息
            readFromClient();
            // 回复客户端说已收到
            sendToClient();
        }

        private void sendToClient() {
            OutputStream outputStream = null;
            // 回复客户端
            try {
                outputStream = socket.getOutputStream();
                // 发送消息给客户端
                outputStream.write("我接收到了".getBytes(StandardCharsets.UTF_8));
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                // 关闭流和连接
                if(outputStream != null) {
                    try {
                        outputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        private void readFromClient() {
            // 接收客户端的数据
            BufferedReader reader = null;
            try {
                System.out.println("开始获取客户端接收的消息");
                // 获取输入流,读取客户端传过来的信息
                reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String line = "";
                while ((line = reader.readLine()) != null) {
                    System.out.println("从客户端接收到一条消息,内容为:" + line);
                }
                System.out.println("结束获取客户端接收的消息");
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                // 关闭流和连接
                if(reader != null) {
                    try {
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

}

package com.alone.study.chat.bio;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ExecutorService;

import static java.util.concurrent.Executors.newFixedThreadPool;

public class ChatClient {

    private int port = 8080;
    private static final ExecutorService EXECUTOR_SERVICE = newFixedThreadPool(1);

    public ChatClient() {
    }

    public ChatClient(int port) {
        this.port = port;
    }

    private void consumer() {
        System.out.println("客户端开始发送数据");
        try {
            Socket client = new Socket("localhost", 8081);
            OutputStream outputStream = client.getOutputStream();
            try {
                outputStream.write("这里是8080端口".getBytes(StandardCharsets.UTF_8));
                System.out.println("客户端结束发送数据");
            } finally {
                if(outputStream != null) {
                    outputStream.close();
                }
                if(client != null) {
                    client.close();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        ChatClient client = new ChatClient();
        client.consumer();
    }
}

不太理解上面这个服务端为啥会报错。

NIO

nio学习笔记

to be continue…

参考资料

1.java的socket连接,聊天室通信实现
2. 简述Socket连接的过程
3. Java网络编程之通过代码实现Socket通信
4. BIO、NIO、AIO实现聊天室功能
5. 同步、异步、阻塞、非阻塞傻傻分不清?

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值