javaIO

一、java网络编程

1、基础知识

a、ip地址和端口号
b、TCP和UDP协议
c、URL
 public static void main(String[] args) throws IOException {
        //使用URL读取网页内容
        //1、创建一个URL实例
        URL url = new URL("http://www.baidu.com");
        InputStream inputStream = url.openStream();// 2、使用openStream()获取资源的字节输入流
        //3、将字节流转换为字符流,如果不指定编码,中文可能会出现乱码
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
        //4、为字符输入流添加缓存,提高读取效率
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        String string = bufferedReader.readLine();  //5、读取数据
        while(string != null) {
            System.out.println(string);  //输出数据
            string = bufferedReader.readLine();
        }
        bufferedReader.close();
        inputStreamReader.close();
        inputStream.close();
    }
d、InetAddress

2、socket

a、创建socket实例
b、客户端连接
步骤:

1)、创建socket对象
2)、建立连接后,通过输出流向服务端发送请求信息
3)、通过输入流获取服务端返回的响应信息
4)、关闭响应资源

public static void main(String[] args) throws IOException {
        //客户端

        //1、创建socket对象
        Socket socket = new Socket("localhost", 10086);

        //2、获取输出流,向服务器发送信息
        OutputStream outputStream = socket.getOutputStream();
        PrintWriter printWriter = new PrintWriter(outputStream);//将输出流包装成打印流
        printWriter.write("用户名: admin; 密码:123");
        printWriter.flush();
        socket.shutdownOutput();

        //3、获取输入流,并读取服务端的响应信息
        InputStream inputStream = socket.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String string = null;
        while((string = bufferedReader.readLine()) != null){
            System.out.println("我是客户端,服务端说:" + string);
        }

        //4、关闭响应资源
        bufferedReader.close();
        inputStream.close();
        printWriter.close();
        outputStream.close();
        socket.close();

    }
c、服务端连接
步骤:

1)、创建ServerSocket对象, 绑定监听端口
2)、通过accept() 方法监听客户端请求
3)、连接建立后,通过输入流读取客户端发送的请求信息
4)、通过输出流向客户端发送信息
5)、关闭相关资源

public static void main(String[] args) throws IOException {
        /**
         *服务端,基于Tcp协议的socket通信,实现用户登录
         */

        //1、创建serverSocket,指定绑定的端口,并监听此端口
        ServerSocket serverSocket = new ServerSocket(10086);

        //2、调用accept()方法开始监听,等待客户端的连接
        Socket socket = serverSocket.accept();

        //3、获取输入流,并读取客户端信息
        InputStream inputStream = socket.getInputStream();
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        String string = null;
        while((string = bufferedReader.readLine()) != null){
            System.out.println("我是服务端,客户端说:"+ string);
        }
        socket.shutdownInput();  //关闭输入流

        //4、获取输出流,向客户端发送信息
        OutputStream outputStream = socket.getOutputStream();
        PrintWriter printWriter = new PrintWriter(outputStream);
        printWriter.write("欢迎您!");
        printWriter.flush();

        //5、关闭资源
        printWriter.close();
        outputStream.close();
        bufferedReader.close();
        inputStreamReader.close();
        inputStream.close();
        socket.close();
        serverSocket.close();

    }
d、总结

1)、创建ServerSocket和Socket
2) 、打开连接到Socket的输入输出流
3)、按照协议对Socket进行读写操作
4)、关闭输入输出流、关闭socket

二、阻塞IO

1、java的IO接口

数据和传输方式是最影响效率的两个方面。

a、基于字节操作的IO接口

b、基于字符操作的IO接口

c、基于磁盘操作的IO接口

d、基于网络操作的IO接口

2、阻塞IO的通信模型

在这里插入图片描述

3、总结

a 、 BIO数据在写入OutputStream和从InputStream读取时,都有可能发生阻塞
b 、当前一些需要大量http长连接的情况
c 、需要另外一种新的IO操作方式

三、NIO

1、工作原理

(补充)
在这里插入图片描述

2、通信模型

(补充)
在这里插入图片描述

3、实例

客户端代码:
public class NIOClient {

    //通道管理器
    private Selector selector;
    /**
     *获取一个socket通道,并对该通道做一些初始化工作
     */
    public void initClient(String ip, int port) throws IOException {

        //获取一个socket通道
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.configureBlocking(false);  //设置通道为非阻塞
        //获取一个通道管理器
        this.selector = Selector.open();

        //客户端连接服务器,其实方法执行并没有实现连接,
        // 需要在Listen()方法中调用channel.finishConnect()才能完成连接
        socketChannel.connect(new InetSocketAddress(ip, port));

        //将通道管理器和该通道绑定,并为该通道注册SelectionKey.OP_CONNECT
        socketChannel.register(selector, SelectionKey.OP_CONNECT);
    }

    /**
     *采用轮寻的方式监听selector上是否有需要处理的事件,如果有,则进行处理
     */
    public void listen() throws IOException{
        //轮寻访问selector
        while (true){
            selector.select();
            //获取selector中选中的项的迭代器
            Iterator iterator = this.selector.selectedKeys().iterator();
            while(iterator.hasNext()){
                SelectionKey selectionKey = (SelectionKey)iterator.next();
                //删除已选的key,以防重复处理
                iterator.remove();
                //连接事件发生
                if(selectionKey.isAcceptable()){
                    SocketChannel socketChannel = (SocketChannel)selectionKey.channel();
                    //如果正在连接,则完成连接
                    if(socketChannel.isConnectionPending()){
                        socketChannel.finishConnect();
                    }

                    //设置成非阻塞
                    socketChannel.configureBlocking(false);
                    //在这里可以给服务器发送消息
                    socketChannel.write(ByteBuffer.wrap(new String("向服务端发送了一条消息").getBytes()));
                    //在和服务端连接成功后,为了可以接收到服务端的消息,需要给通道设置读的权限
                    socketChannel.register(this.selector, SelectionKey.OP_READ);

                }else if(selectionKey.isReadable()){//获取了可读的条件
                    read(selectionKey);
                }
            }
        }
    }

    /**
     * 处理读取服务端发送来的信息的事件
     */
    public void read(SelectionKey selectionKey){
        //和服务端的read方法一样

    }
}
服务端代码
public class NIOServer {

    //通道管理器
    private Selector selector;
    /**
     *获取一个ServerSocket通道,并对该通道做一些初始化工作
     */
    public void initServer(int port) throws IOException {

        //获取一个ServerSocket通道
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //设置通道为非阻塞
        serverSocketChannel.configureBlocking(false);
        //将该通道对应的ServerSocket绑定到端口
        serverSocketChannel.socket().bind(new InetSocketAddress(port));
        //获得一个通道管理器
        selector = Selector.open();

        //将通道管理器和该通道进行绑定,并为该通道注册SelectionKey.OP_ACCEPT事件,注册该事件后,
        // 当事件到达时,selector.select()会返回,如果该事件没到达,selector.select()会一直阻塞
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

    }

    /**
     *采用轮寻的方式监听selector上是否有需要处理的事件,如果有,则进行处理
     */
    public void listen() throws IOException{
       System.out.println("服务器启动成功");
       //轮寻访问selector
        while(true){
            //当注册的事件到达时,方法返回,否则,该方法一直阻塞
            selector.select();
            //获取selector中选中的项的迭代器,选中的项为注册的事件
            Iterator iterator = this.selector.selectedKeys().iterator();
            if(iterator.hasNext()){
                SelectionKey selectionKey = (SelectionKey) iterator.next();
                //删除已选的key,以防重复处理
                iterator.remove();
                //客户端请求连接事件
                if(selectionKey.isAcceptable()){
                    ServerSocketChannel serverSocketChannel = (ServerSocketChannel)selectionKey.channel();

                    //获得和客户端连接的通道
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    //设置成非阻塞
                    socketChannel.configureBlocking(false);

                    //在这里可以给客户端发送消息
                    socketChannel.write(ByteBuffer.wrap(new String("向客户端发送一条消息").getBytes()));

                    //在和客户端连接成功后,为了可以接收到客户端的信息,需要给通道设置读的权限
                    socketChannel.register(this.selector, SelectionKey.OP_READ);

                }else if(selectionKey.isReadable()) {  //获得了可以读的权限
                    read(selectionKey );
                }
            }

        }

    }

    /**
     * 处理读取客户端发送来的信息的事件
     */
    public void read(SelectionKey selectionKey) throws IOException{
        //服务端可以读取消息: 得到事件发生的socket通道
        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
        //创建读取的缓存区
        ByteBuffer byteBuffer = ByteBuffer.allocate(10);
        socketChannel.read(byteBuffer);
        byte[] data = byteBuffer.array();
        String msg = new String(data).trim();

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值