BIO、NIO

BIO:
是一种阻塞的IO
客户端:

import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;

public class Client {

    public static void main(String[] args) {
        try {
            Socket socket=new Socket("127.0.0.1",8080);//3.客户端Socket对象
            Scanner scanner=new Scanner(System.in);
            String text=scanner.nextLine();
            socket.getOutputStream().write(text.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

服务器端:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {

    static  byte[] bytes=new byte[1024];
    public static void main(String[] args) {

        try {
            ServerSocket serverSocket=new ServerSocket();//1.这个Socket对象是用来监听的·listener;
            serverSocket.bind(new InetSocketAddress(8080));

            System.out.println("等待连接");
            /*阻塞*/
            Socket socket=serverSocket.accept();//2.这个Socket对象,是专门用来和客户端进行通信的Socket         accept方法会导致阻塞,直到该服务器端接收到一个客户端对象,代码才会往下继续运行
            System.out.println("连接成功");

            System.out.println("等待读取数据");

            /*阻塞  value表示读了多少字节,读了多少数据*/
            int value=socket.getInputStream().read(bytes);//read会阻塞,直到客户端发送了数据,代码才会往下继续运行
            System.out.println("读取数据成功");
            String content=new String(bytes);
            System.out.println(value+":"+content);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在客户端与服务器端进行通信时,是有3个Socket对象的:1.客户端Socket对象;2.服务器端用来监听的Socket对象;3.服务器端用来通信的Socket对象;

上面这段代码中,服务器端只能接受一个客户端,原因就在于:(1)服务器端在获取客户端连接(accept)处是会阻塞的,直到获取到一个客户端的Socket对象,服务器端代码才往下继续执行;(2)服务器端在读取客户端发送的数据(read)处也是会阻塞的,直到读取到数据,服务器端代码才会往下继续执行;

以上两个原因导致当获取到一个客户端的Socket对象之后,服务器端被阻塞时,服务器端无法再接收其他的客户端对象,导致其无法并发处理,因此要想使其进行并发处理,就要使用多线程来处理;
但还有另外一种方式,使用一种类似于NIO的方式:使服务器端在获取客户端连接时,在accept的过程中,不会被阻塞,即使没有获取到客户端Socket对象,代码也能往下进行;且在读取客户端数据时,也不会被阻塞,即使没有读取到数据,使其仍能往下执行;

configureBlocking(false);的作用就是改变Socket对象的通信模式,false代表将其改为非阻塞模式;

NIO:
非阻塞的IO

客户端代码不变

客户端:

import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;

public class Client {

    public static void main(String[] args) {
        try {
            Socket socket=new Socket("127.0.0.1",8080);

            Scanner scanner=new Scanner(System.in);
            while(scanner.hasNext()){
                String text=scanner.nextLine();
                socket.getOutputStream().write(text.getBytes());
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

服务器端:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.HashSet;
import java.util.Set;

public class Server {

    private static Set<SocketChannel> set = new HashSet<>();//在该集合中存放所有的客户端对象
    private static  byte[] bytes=new byte[1024];
    public static void main(String[] args) {

        try {
            ServerSocketChannel serverSocket = ServerSocketChannel.open();
            serverSocket.bind(new InetSocketAddress(8080));
            serverSocket.configureBlocking(false);//设置为非阻塞的,这样子当服务器端在进行accept时,无论是否接收到客户端,代码都能往下运行
            while (true) {
                System.out.println("等待连接");
                SocketChannel socket = serverSocket.accept();
                if (socket == null) {
                    Thread.sleep(1000);
                    System.out.println("无人连接");
                } else {
                    socket.configureBlocking(false);//将其设置为非阻塞,这样子,当读取客户端数据时,不会阻塞,代码会继续往下运行
                    set.add(socket);//将其添加到集合中
                    System.out.println("连接成功");
                    System.out.println("等待读取数据");
                }

                 /*遍历整个集合,看所有的客户端是否有向服务器端发送数据*/
                for (SocketChannel item : set) {
                   
                    int value=item.read(ByteBuffer.wrap(bytes));
                    if(value>0) {
                        String content=new String(bytes);
                        System.out.println(content);
                    }
                }
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

上面代码中:
(1)serverSocket.configureBlocking(false);//设置为非阻塞的,这样子当服务器端在进行accept时,无论是否接收到客户端,代码都能往下运行
(2) socket.configureBlocking(false);//将其设置为非阻塞,这样子,当读取客户端数据时,不会阻塞,不管客户端有没有发送数据,代码都会继续往下运行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值