栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

网络编程之channel

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

网络编程之channel

介绍
  • Channel 是一个对象,可以通过它读取和写入数据。
  • 拿 NIO 与原来的 I/O 做个比较,通道就像是流。
  • 所有数据都通过 Buffer 对象来处理。您永远不会将字节直接写入通道中,相反,您是将数据写入包含一个或者多个字节的缓冲区。
  • 同样,您不会直接从通道中读取字节,而是将数据从通道读入缓冲区,再从缓冲区获取这个字节。
各种Channel FileChannel
package com.yangmin.study.io.nio.channel;

import java.io.*;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;


public class ChannelTest {

    public static void main(String[] args) {
        ChannelTest channelTest = new ChannelTest();
//        channelTest.fileChannelRead();
//        channelTest.fileChannelWrite();
        channelTest.transferFrom();
    }

    


    
    void fileChannelRead() {

        
        FileInputStream fileInputStream = null;
        FileChannel channel = null;
        try {
            fileInputStream = new FileInputStream("src/main/resources/read.text");
            channel = fileInputStream.getChannel();
            
            ByteBuffer buffer = ByteBuffer.allocate(14);
            while (channel.read(buffer) != -1) {
                //第一次进来的时候,buffer为:[pos=7 lim=14 cap=14]
                System.out.println(buffer.toString());
                System.out.println(new String(buffer.array()));
                buffer.clear();
            }
            System.out.println(channel.position());
            System.out.println(channel.size());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (channel != null) {
                try {
                    channel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }


    
    void fileChannelWrite() {
        FileOutputStream fileOutputStream = null;
        FileChannel channel = null;
        try {
            fileOutputStream = new FileOutputStream("src/main/resources/write.text");
            channel = fileOutputStream.getChannel();
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            buffer.clear();
            buffer.put(("注意 FileChannel.write()是在 while 循环中调用的。因为无法保证 write()方法一次能向 " +
                    "FileChannel 写入多少字节,因此需要重复调用 write()方法," +
                    "直到 Buffer 中已经没有尚未写入通道的字节。").getBytes());
            System.out.println(buffer.toString());
            //切换为读模式,切换后可以读取buffer中的数据
            // H T T P / 1 ... ! _  _
            //                   P(L)
            // P                 L
            buffer.flip();
            System.out.println(buffer.toString());
            while (buffer.hasRemaining()) { //当position==limit时,说明已经把buffer中的数据读完了
                channel.write(buffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //用完 FileChannel 后必须将其关闭。如:  inChannel.close();
            if (channel != null) {
                try {
                    channel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    
    void transferFrom() {
        RandomAccessFile readFile = null;
        RandomAccessFile writeFile = null;
        try {
            readFile = new RandomAccessFile("src/main/resources/read.text", "rw");
            writeFile = new RandomAccessFile("src/main/resources/write.text", "rw");
            FileChannel fromChannel = readFile.getChannel();
            FileChannel toChannel = writeFile.getChannel();
            
            
            //设置起始/结束位置
            long position = 0;
            long count = fromChannel.size();
            
            //long l = toChannel.transferFrom(fromChannel, position, count);

            
            long l = fromChannel.transferTo(position, count, toChannel);
            System.out.println(l);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (readFile != null) {
                    readFile.close();
                }
                if (writeFile != null) {
                    writeFile.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

ServerSocketChannel
  • nio服务端
  • ServerSocketChannel 是一个基于通道的 socket 监听器(本身不传数据,而是一个监听器)。
  • 由于 ServerSocketChannel 没有 bind()方法,因此有必要取出对等的 socket 并使用它来绑定到一个端口以开始监听连接。我们也是使用对等 ServerSocket 的 API 来根据需要设置其他的 socket 选项。
package com.yangmin.study.io.nio.channel;

import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;


public class ServerSocketChannelTest {


    public static void main(String[] args) {

        ServerSocketChannelTest serverSocketChannelTest = new ServerSocketChannelTest();
        serverSocketChannelTest.test1();
    }

    void test1() {
        try {
            
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            
            ServerSocket serverSocket = serverSocketChannel.socket();
            serverSocket.bind(new InetSocketAddress(8888));
            
            serverSocketChannel.configureBlocking(false);
            
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            for (; ; ) {
                
                //我们这里采用的是非阻塞模式
                SocketChannel socketChannel = serverSocketChannel.accept();
                if (socketChannel == null) {
                    System.out.println("null");
                    Thread.sleep(2000);
                    continue;
                }
                
                socketChannel.read(buffer);
                System.out.println("this is a data from client, "+new String(buffer.array()));
                //重置position=0,进行写操作
                buffer.rewind();
                buffer.put("hello client, i am server".getBytes());
                //切换为读操作
                buffer.flip();
                
                socketChannel.write(buffer);
                buffer.clear();
                socketChannel.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

SocketChannel

nio客户端
1、SocketChannel 介绍
Java NIO 中的 SocketChannel 是一个连接到 TCP 网络套接字的通道。操作面向Buffer缓冲区
A selectable channel for stream-oriented connecting sockets,这是 Java docs 中对于 SocketChannel 的描述:SocketChannel 是一种面向流连接sockets 套接字的可选择通道。从这里可以看出:

  • SocketChannel 是用来连接 Socket 套接字
  • SocketChannel 主要用途用来处理网络 I/O 的通道
  • SocketChannel 是基于 TCP 连接传输
  • SocketChannel 实现了可选择通道,可以被多路复用的
  • 用于TCP的网络I/O套接字的通道
    2、SocketChannel 特征:
    (1)对于已经存在的 socket 不能创建 SocketChannel
    (2)SocketChannel 中提供的 open 接口创建的 Channel 并没有进行网络级联,需要使用 connect 接口连接到指定地址
    (3)未进行连接的 SocketChannle 执行 I/O 操作时,会抛出NotYetConnectedException
    (4)SocketChannel 支持两种 I/O 模式:阻塞式和非阻塞式
    (5)SocketChannel 支持异步关闭。如果 SocketChannel 在一个线程上 read 阻塞,另一个线程对该 SocketChannel 调用 shutdownInput,则读阻塞的线程将返回-1 表示没有读取任何数据;如果 SocketChannel 在一个线程上 write 阻塞,另一个线程对该SocketChannel 调用 shutdownWrite,则写阻塞的线程将抛出AsynchronousCloseException
    (6)SocketChannel 支持设定参数
    SO_SNDBUF 套接字发送缓冲区大小
    SO_RCVBUF 套接字接收缓冲区大小
    SO_KEEPALIVE 保活连接
    O_REUSEADDR 复用地址
    SO_LINGER 有数据传输时延缓关闭 Channel (只有在非阻塞模式下有用)
    TCP_NODELAY 禁用 Nagle 算法
package com.yangmin.study.io.nio.channel;

import jdk.nashorn.internal.ir.Block;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;


public class SocketChannelTest {

    public static void main(String[] args) {

        SocketChannelTest socketChannelTest = new SocketChannelTest();
       // socketChannelTest.unBlock();
        socketChannelTest.block();
    }

    
    void block(){
        System.out.println("connect start");
        SocketChannel socketChannel = null;
        try {

            
            socketChannel = SocketChannel.open();
            socketChannel.connect(new InetSocketAddress("127.0.0.1",8888));

            //SocketChannel.open(new InetSocketAddress("127.0.0.1",8888));

            
            if (socketChannel.isConnected()){
                System.out.println("connect server success");
            }
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            buffer.put("hello serverrn".getBytes());
            buffer.flip();
            socketChannel.write(buffer);
            System.out.println("send data to server");
            buffer.clear();
            socketChannel.read(buffer);
            System.out.println("accept data from server :"+new String(buffer.array()));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (socketChannel!=null){
                try {
                    socketChannel.close();
                    System.out.println("aaaaaaaa");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    
    void unBlock(){
        System.out.println("connect start");
        SocketChannel socketChannel = null;
        try {
            socketChannel = SocketChannel.open();
            socketChannel.connect(new InetSocketAddress("127.0.0.1",8888));
            //设置 SocketChannel 的读写模式。false 表示非阻塞,true 表示阻塞
            socketChannel.configureBlocking(false);
            if (socketChannel.isConnected()){
                System.out.println("connect server success");
            }
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            buffer.put("hello serverrn".getBytes());
            buffer.flip();
            socketChannel.write(buffer);
            System.out.println("send data to server");
            buffer.clear();
            socketChannel.read(buffer);
            System.out.println("accept data from server :"+new String(buffer.array()));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (socketChannel!=null){
                try {
                    socketChannel.close();
                    System.out.println("aaaaaaaa");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    
}

DatagramChannel

发包

package com.yangmin.study.io.nio.channel;


import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;


public class DatagramChannelSendTest {

    public static void main(String[] args) {
        DatagramChannelSendTest datagramChannelTest = new DatagramChannelSendTest();
        datagramChannelTest.sendData();
    }

    
    private void sendData() {
        try {
            DatagramChannel datagramChannel = DatagramChannel.open();
            
            InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 8888);
            datagramChannel.send(ByteBuffer.wrap("发包".getBytes()), inetSocketAddress);
            Thread.sleep(2000);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

收包

package com.yangmin.study.io.nio.channel;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;


public class DatagramChannelAcceptTest {
    public static void main(String[] args) throws IOException {
        DatagramChannel server = DatagramChannel.open();
        InetSocketAddress socketAddress = new InetSocketAddress(8888);
        server.bind(socketAddress);
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        while (true){
            buffer.clear();
            server.receive(buffer);
            System.out.println(new String(buffer.array()));
            System.out.println("发来信息的ip地址:"+socketAddress.toString());
        }

    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/975632.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号