国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Java-NIO篇章(3)——Channel通道類詳解

這篇具有很好參考價值的文章主要介紹了Java-NIO篇章(3)——Channel通道類詳解。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

Java NIO中,一個socket連接使用一個Channel(通道)來表示。對應到不同的網(wǎng)絡傳輸協(xié)議類型,在Java中都有不同的NIO Channel(通道) 相對應。其中最為重要的四種Channel(通道)實現(xiàn): FileChannel、 SocketChannel、 ServerSocketChannel、 DatagramChannel :

  • FileChannel 文件通道,用于文件的數(shù)據(jù)讀寫; (管文件的傳輸通道)
  • SocketChannel 套接字通道,用于Socket套接字TCP連接的數(shù)據(jù)讀寫; (管TCP數(shù)據(jù)傳輸?shù)耐ǖ溃?/li>
  • ServerSocketChannel 服務器套接字通道(或服務器監(jiān)聽通道),允許我們監(jiān)聽TCP連接請求,為每個監(jiān)聽到的請求,創(chuàng)建一個SocketChannel套接字通道; (只管與服務器 TCP連接 的通道)
  • DatagramChannel 數(shù)據(jù)報通道,用于UDP協(xié)議的數(shù)據(jù)讀寫。 (管UDP數(shù)據(jù)傳輸?shù)耐ǖ?

我在學習Channel的時候,老是搞不清楚ServerSocketChannelSocketChannel的關系,這次我不允許我的讀者也搞不清。用大白話講就是通道你可以理解為數(shù)據(jù)傳輸?shù)墓艿?,這個管道是雙向傳輸?shù)?,即既可以通過Channel向文件或者網(wǎng)絡客戶端寫數(shù)據(jù)也可以從文件或者網(wǎng)絡客戶端讀數(shù)據(jù)。如果你要讀取文件的數(shù)據(jù),使用FileChannel ;如果需要建立網(wǎng)絡連接,在服務器使用ServerSocketChannel 來作為客戶端連接請求的通道,也就是說它只負責服務器端的連接請求的數(shù)據(jù)傳輸。通過ServerSocketChannel就可以和服務器建立連接,然后通過ServerSocketChannel創(chuàng)建SocketChannel 通道進行TCP數(shù)據(jù)傳輸。下面分別介紹每一個通道的用法。

FileChannel文件通道

FileChannel是專門操作文件的通道。通過FileChannel,既可以從一個文件中讀取數(shù)據(jù),也可以將數(shù)據(jù)寫入到文件中。特別申明一下, FileChannel為阻塞模式,不能設置為非阻塞模式。不說你也知道,學習IO操作可以首先要獲取FileChannel通道 、然后讀取FileChannel通道中的數(shù)據(jù)或者將數(shù)據(jù)寫入FileChannel通道,然后關閉通道。最后補充一個就是強制將通道的數(shù)據(jù)刷盤到磁盤的方法即可,那么就按照上面的步驟開始吧!

獲取到FileChannel對象

獲取FileChannel對象有三種方式,第一種方式可以通過文件的輸入流、輸出流獲取FileChannel文件通道,代碼如下:

//創(chuàng)建一個文件輸入流
FileInputStream fis = new FileInputStream("word.txt");
//獲取文件流的通道,只能從通道中讀取數(shù)據(jù),不能寫入數(shù)據(jù)
FileChannel inChannel = fis.getChannel();

//創(chuàng)建一個文件輸出流
FileOutputStream fos = new FileOutputStream("word.txt");
//獲取文件流的通道,只能向通道中寫入數(shù)據(jù),不能讀取數(shù)據(jù)
FileChannel outchannel = fos.getChannel();

也可以通過RandomAccessFile文件隨機訪問類,獲取FileChannel文件通道實例,代碼如下:

// 創(chuàng)建 既可以寫也可以讀的隨機訪問類 RandomAccessFile 隨機訪問對象
// 參數(shù)"rw"表示可讀可寫,如果只讀可以給"r",只寫給"w"即可
RandomAccessFile rFile = new RandomAccessFile("word.txt", "rw");
//獲取文件流的通道(可讀可寫)
FileChannel channel = rFile.getChannel();

從FileChannel中讀取數(shù)據(jù)

下面給出標準的讀取數(shù)據(jù)的代碼,具體解釋在注釋中,代碼中channel.read(buffer)將通道的數(shù)據(jù)讀到緩沖區(qū)上,雖然是讀取通道的數(shù)據(jù),對于通道來說是讀取模式,但是對于ByteBuffer緩沖區(qū)來說則是寫入數(shù)據(jù),這時, ByteBuffer緩沖區(qū)處于寫入模式 ,而buffer.get()才是從通道讀取數(shù)據(jù),需要flip()切換讀模式:

try(FileChannel channel = new RandomAccessFile("word.txt", "rw").getChannel()){
    // 準備緩沖區(qū),分配10字節(jié)的空間
    ByteBuffer buffer = ByteBuffer.allocate(10);
    int len = -1;
    while ((len=channel.read(buffer))!=-1){ // 將channel中的數(shù)據(jù)讀取到緩存區(qū)中,返回讀到的數(shù)據(jù)長度,沒讀到數(shù)據(jù)返回-1
        buffer.flip(); // 切換讀取模式,左右指針指向已存數(shù)據(jù)首位
        while (buffer.hasRemaining()){// 如果position<limit,即還可以讀
            byte b = buffer.get();//讀取字節(jié)流,讀指針向后移動一個位置,補充buffer.get(i)可以讀取指定坐標的字節(jié)
            log.debug("讀取到的字節(jié):"+(char)b); //  log.debug 可以換成 System.out.println
        }
        buffer.clear(); // 讀完了buffer,將buffer的指針重新回歸buffer首尾
        //buffer.compact(); // 如果未讀完, 壓縮,將未讀的放在左邊
    }
}catch (IOException e){
    log.error("文件未找到");
}

上面將byte轉(zhuǎn)為char類型需要解釋一下:字節(jié)是8位,而char是16位,因此在將字節(jié)轉(zhuǎn)換為char時,只有低8位的數(shù)據(jù)被使用,高8位的數(shù)據(jù)被丟棄。這意味著字節(jié)的范圍[-128, 127]將被映射到char的范圍[0, 255],只看整數(shù)部分相當于int類型轉(zhuǎn)為long類型,上轉(zhuǎn)型。如果字節(jié)表示的是ASCII字符,那么這種轉(zhuǎn)換通常是安全的,因為ASCII字符的范圍是0到127。因為wold.txt中的只有英文字符所以沒問題,有漢字不行。一般不會這樣使用,只是舉下例子!

輸出結(jié)果:輸出wold.txt中的字符:

20:41:37 [DEBUG] [main] c.c.FileChannelTest - 讀取到的字節(jié):h
20:41:37 [DEBUG] [main] c.c.FileChannelTest - 讀取到的字節(jié):e
20:41:37 [DEBUG] [main] c.c.FileChannelTest - 讀取到的字節(jié):l
20:41:37 [DEBUG] [main] c.c.FileChannelTest - 讀取到的字節(jié):l
20:41:37 [DEBUG] [main] c.c.FileChannelTest - 讀取到的字節(jié):o
20:41:37 [DEBUG] [main] c.c.FileChannelTest - 讀取到的字節(jié):
20:41:37 [DEBUG] [main] c.c.FileChannelTest - 讀取到的字節(jié):w
20:41:37 [DEBUG] [main] c.c.FileChannelTest - 讀取到的字節(jié):o
20:41:37 [DEBUG] [main] c.c.FileChannelTest - 讀取到的字節(jié):r
20:41:37 [DEBUG] [main] c.c.FileChannelTest - 讀取到的字節(jié):l
20:41:37 [DEBUG] [main] c.c.FileChannelTest - 讀取到的字節(jié):d

向FileChannel通道中寫數(shù)據(jù)

寫入數(shù)據(jù)到通道,在大部分應用場景,都會調(diào)用通道的write(ByteBuffer)方法,此方法的參數(shù)是一個ByteBuffer緩沖區(qū)實例,是待寫數(shù)據(jù)的來源。write(ByteBuffer)方法的作用,是從ByteBuffer緩沖區(qū)中讀取數(shù)據(jù),然后寫入到通道自身,而返回值是寫入成功的字節(jié)數(shù)。如果 buffer 處于寫入模式(如剛寫完數(shù)據(jù)),需要 flip 翻轉(zhuǎn) buffer,使其變成讀取模式,代碼如下:

@Test
public void test2(){
	// wrap 方法執(zhí)行完自動切換wrapBuffer為讀模式
	ByteBuffer wrapBuffer = ByteBuffer.wrap("你好世界!".getBytes());
	try(FileChannel channel = new RandomAccessFile("word.txt","rw").getChannel()){
        int len = 0;
        while ((len = channel.write(wrapBuffer))!=0){
        	System.out.println("已經(jīng)寫入字節(jié)數(shù)為:"+len); //已經(jīng)寫入字節(jié)數(shù)為:15
        }
    }catch (IOException e){
     	log.error("文件未找到");
	}
}

// 關閉通道
channel.close();
//強制刷新到磁盤
channel.force(true);

注意,寫入數(shù)據(jù)會將word.txt原有的數(shù)據(jù)擦除!當通道使用完成后,必須將其關閉。關閉非常簡單,調(diào)用close( )方法即可 。如果在將緩沖數(shù)據(jù)寫入通道時,需要保證數(shù)據(jù)能立即寫入到磁盤,可以在寫入后調(diào)用一下FileChannel的force()方法。關于FileChannel通道需要掌握的大概就是上面這些,那么下面的內(nèi)容是作為開發(fā)中的補充內(nèi)容。

文件操作補充內(nèi)容

字符串與ByteBuffer緩存的相互轉(zhuǎn)換
// 字符串轉(zhuǎn)為ByteBuffer
ByteBuffer buffer = ByteBuffer.allocate(16);
buffer.put("hello world".getBytes());
debugAll(buffer);

buffer.flip(); //這種方式需要切換讀模式才可以
CharBuffer hw = StandardCharsets.UTF_8.decode(buffer);
System.out.println(hw.toString());

// 使用Charset類
ByteBuffer encodeBuffer = StandardCharsets.UTF_8.encode("hello");
debugAll(encodeBuffer);

CharBuffer decode = StandardCharsets.UTF_8.decode(encodeBuffer);
System.out.println(decode.toString());

// 使用wrap
ByteBuffer wrapBuffer = ByteBuffer.wrap("hello".getBytes());
debugAll(wrapBuffer);
通道與通道直接發(fā)送數(shù)據(jù)(零拷貝)
public static void main(String[] args) {
    try(
            FileChannel from = new FileInputStream("world.txt").getChannel();
            FileChannel to = new FileOutputStream("to.txt").getChannel()
    ) {
        long size = from.size();
        for (long left = size; left >0 ; ) {
            // 該方法每次最多傳輸2g的數(shù)據(jù)量
            long n = from.transferTo((size-left), from.size(), to);
            left -= n;
        }
    }catch (IOException ie){
        ie.printStackTrace();
    }
}
NIO提供的關于File的操作

遍歷目錄文件:

public class FileTest {
    public static void main(String[] args) throws IOException {
        // 訪問文件夾
        visitorFile();
        // 拷貝文件夾
        copyFile();
        // 刪除文件夾
        deleteFile();

    }

    private static void copyFile() throws IOException {
        String source = "C:\\Users\\cheney\\Documents\\CFSystem";
        String target = "C:\\Users\\cheney\\Documents\\CFSystem_bak";

        Files.walk(Paths.get(source)).forEach(path -> {
            // 替換成新的路徑
            String targetName = path.toString().replace(source, target);
            try {
                if(Files.isDirectory(path)){
                    Files.createDirectory(Paths.get(targetName));
                }else if(Files.isRegularFile(path)){
                    Files.copy(path,Paths.get(targetName));
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        });
    }

    private static void deleteFile() throws IOException {
        Files.walkFileTree(Paths.get("C:\\Users\\cheney\\Documents\\CFSystem_bak"),new SimpleFileVisitor<Path>(){
            @Override
            // 在訪問目錄之前被調(diào)用。你可以在這里執(zhí)行預處理操作。
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                // 進入文件夾時不能刪除文件夾,因為里面還有文件
                System.out.println("進入------>"+dir);
                return super.preVisitDirectory(dir, attrs);
            }

            @Override
            // 在訪問某個目錄的文件時被調(diào)用。你可以在這里執(zhí)行對文件的操作。
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                // 刪除文件夾
                System.out.println("刪除xxxxxx:"+file);
                Files.delete(file);
                return super.visitFile(file, attrs);
            }

            @Override
            // 在訪問文件失敗時被調(diào)用。例如,由于權限問題或其他原因,無法訪問文件。
            public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
                return super.visitFileFailed(file, exc);
            }

            @Override
            // 在訪問目錄之后被調(diào)用。你可以在這里執(zhí)行后處理操作。
            public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                // 如果退出之前遍歷刪除過文件,那么可以刪除文件夾
                System.out.println("退出<------"+dir);
                Files.delete(dir);
                return super.postVisitDirectory(dir, exc);
            }
        });
    }

    private static void visitorFile() throws IOException {
        AtomicInteger dirCount = new AtomicInteger();
        // 遍歷文件夾,SimpleFileVisitor訪問者模式
        Files.walkFileTree(Paths.get("C:\\Users\\cheney\\Documents\\CFSystem"),new SimpleFileVisitor<Path>(){
            // 文件訪問之前的操作,即訪問到文件夾
            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                System.out.println("==========>"+dir);
                dirCount.incrementAndGet();
                return super.preVisitDirectory(dir, attrs);
            }

            // 文件訪問時操作,即訪問到文件
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                System.out.println("==========>"+file);
                return super.visitFile(file, attrs);
            }
        });
        System.out.println("文件夾個數(shù):"+dirCount.get());
    }
}

檢查文件是否存在

Path path = Paths.get("helloword/data.txt");
System.out.println(Files.exists(path));

創(chuàng)建一級目錄

Path path = Paths.get("helloword/d1");
Files.createDirectory(path);
  • 如果目錄已存在,會拋異常 FileAlreadyExistsException
  • 不能一次創(chuàng)建多級目錄,否則會拋異常 NoSuchFileException

創(chuàng)建多級目錄用

Path path = Paths.get("helloword/d1/d2");
Files.createDirectories(path);

拷貝文件

Path source = Paths.get("helloword/data.txt");
Path target = Paths.get("helloword/target.txt");

Files.copy(source, target);
  • 如果文件已存在,會拋異常 FileAlreadyExistsException

如果希望用 source 覆蓋掉 target,需要用 StandardCopyOption 來控制

Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);

移動文件

Path source = Paths.get("helloword/data.txt");
Path target = Paths.get("helloword/data.txt");

Files.move(source, target, StandardCopyOption.ATOMIC_MOVE);
  • StandardCopyOption.ATOMIC_MOVE 保證文件移動的原子性

刪除文件

Path target = Paths.get("helloword/target.txt");

Files.delete(target);
  • 如果文件不存在,會拋異常 NoSuchFileException

刪除目錄

Path target = Paths.get("helloword/d1");

Files.delete(target);
  • 如果目錄還有內(nèi)容,會拋異常 DirectoryNotEmptyException

SocketChannel和ServerSocketChannel套接字通道

很多人都搞不拎清這兩個通道的區(qū)別,它們都是涉及網(wǎng)絡連接的通道,SocketChannel負責連接的數(shù)據(jù)傳輸,另一個是ServerSocketChannel負責連接的監(jiān)聽。要想和服務器建立TCP通信,必須先連接服務器,而ServerSocketChannel就是符合客戶端連接請求的通道,只有三次握手連接完成了才可以使用SocketChannel進行通信。ServerSocketChannel僅僅應用于服務器端,而SocketChannel則同時處于服務器端和客戶端,所以,對應于一個連接,兩端都有一個負責傳輸?shù)腟ocketChannel傳輸通道。同樣下面講解將按照獲取通道、讀取通道數(shù)據(jù)、數(shù)據(jù)寫入到通道中、關閉通道等步驟介紹。

獲取SocketChannel傳輸通道

在客戶端,先通過SocketChannel靜態(tài)方法open()獲得一個套接字傳輸通道;然后,將socket套接字設置為非阻塞模式;最后,通過connect()實例方法,對服務器的IP和端口發(fā)起連接。

//獲得一個套接字傳輸通道
SocketChannel socketChannel = SocketChannel.open();
//設置為非阻塞模式
socketChannel.configureBlocking(false);
//對服務器的 IP 和端口發(fā)起連接
socketChannel.connect(new InetSocketAddress("127.0.0.1"80));

在服務器端,需要在連接建立的事件到來時,服務器端的ServerSocketChannel能成功地查詢出這個新連接事件,并且通過調(diào)用服務器端ServerSocketChannel監(jiān)聽套接字的accept()方法,來獲取新連接的套接字通道:

//新連接事件到來,首先通過事件,獲取服務器監(jiān)聽通道,這個key如何來的后面Selector會介紹
ServerSocketChannel server = (ServerSocketChannel) key.channel();
//獲取新連接的套接字通道
SocketChannel socketChannel = server.accept();
//設置為非阻塞模式
socketChannel.configureBlocking(false);

看見了沒,服務器端需要先使用ServerSocketChannel建立連接才能使用套接字傳輸通道!

讀取SocketChannel傳輸通道

當SocketChannel傳輸通道可讀時,可以從SocketChannel讀取數(shù)據(jù),具體方法與前面的文件通道讀取方法是相同的。調(diào)用read方法,將數(shù)據(jù)讀入緩沖區(qū)ByteBuffer。 這部分和前面文件傳輸通道FileChannel是一樣的,都是通過緩沖區(qū)從通道讀取和寫入數(shù)據(jù),如下:

ByteBuffer buffer = ByteBuffer.allocate(1024);
int bytesRead = socketChannel.read(buffer);

在讀取時,因為是異步的,因此我們必須檢查read的返回值,以便判斷當前是否讀取到了數(shù)據(jù)。 read()方法的返回值是讀取的字節(jié)數(shù),如果返回-1,那么表示讀取到對方的輸出結(jié)束標志,對方已經(jīng)輸出結(jié)束,準備關閉連接。實際上,通過read方法讀數(shù)據(jù),本身是很簡單的,比較困難的是,在非阻塞模式下,如何知道通道何時是可讀的呢?這就需要用到NIO的新組件——Selector通道選擇器,稍后介紹。

向SocketChannel傳輸通道寫入數(shù)據(jù)

//寫入前需要讀取緩沖區(qū),要求 ByteBuffer 是讀取模式
buffer.flip();
socketChannel.write(buffer);

關閉通道

//調(diào)用終止輸出方法,向?qū)Ψ桨l(fā)送一個輸出的結(jié)束標志
socketChannel.shutdownOutput();
//關閉套接字連接
IOUtil.closeQuietly(socketChannel);

DatagramChannel數(shù)據(jù)報通道

在Java中使用UDP協(xié)議傳輸數(shù)據(jù),比TCP協(xié)議更加簡單。和Socket套接字的TCP傳輸協(xié)議不同, UDP協(xié)議不是面向連接的協(xié)議。使用UDP協(xié)議時,只要知道服務器的IP和端口,就可以直接向?qū)Ψ桨l(fā)送數(shù)據(jù)。在Java NIO中,使用DatagramChannel數(shù)據(jù)報通道來處理UDP協(xié)議的數(shù)據(jù)傳輸。

獲取DatagramChannel數(shù)據(jù)報通道

//獲取 DatagramChannel 數(shù)據(jù)報通道
DatagramChannel channel = DatagramChannel.open();
//設置為非阻塞模式
datagramChannel.configureBlocking(false);

如果需要接收數(shù)據(jù),還需要調(diào)用bind方法綁定一個數(shù)據(jù)報的監(jiān)聽端口,具體如下://調(diào)用 bind 方法綁定一個數(shù)據(jù)報的監(jiān)聽端口```

channel.socket().bind(new InetSocketAddress(18080));

讀取DatagramChannel數(shù)據(jù)報通道數(shù)據(jù)

當DatagramChannel通道可讀時,可以從DatagramChannel讀取數(shù)據(jù)。和前面的SocketChannel讀取方式不同,這里不調(diào)用read方法,而是調(diào)用receive(ByteBufferbuf)方法將數(shù)據(jù)從DatagramChannel讀入,再寫入到ByteBuffer緩沖區(qū)中。通道讀取receive(ByteBufferbuf)方法雖然讀取了數(shù)據(jù)到buf緩沖區(qū),但是其返回值是SocketAddress類型,表示返回發(fā)送端的連接地址(包括IP和端口)。通過receive方法讀取數(shù)據(jù)非常簡單,但是,在非阻塞模式下,如何知道DatagramChannel通道何時是可讀的呢?和SocketChannel一樣,同樣需要用到NIO的新組件—Selector通道選擇器,稍后介紹。

//創(chuàng)建緩沖區(qū)
ByteBuffer buf = ByteBuffer.allocate(1024);
//從 DatagramChannel 讀入,再寫入到 ByteBuffer 緩沖區(qū)
SocketAddress clientAddr= datagramChannel.receive(buf);

寫入DatagramChannel數(shù)據(jù)報通道

向DatagramChannel發(fā)送數(shù)據(jù),和向SocketChannel通道發(fā)送數(shù)據(jù)的方法也是不同的。這里不是調(diào)用write方法,而是調(diào)用send方法。由于UDP是面向非連接的協(xié)議,因此,在調(diào)用send方法發(fā)送數(shù)據(jù)的時候,需要指定接收方的地址(IP和端口)。 示例代碼如下:

//把緩沖區(qū)翻轉(zhuǎn)到讀取模式
buffer.flip();
//調(diào)用 send 方法,把數(shù)據(jù)發(fā)送到目標 IP+端口
dChannel.send(buffer, new InetSocketAddress("127.0.0.1",18899));
//清空緩沖區(qū),切換到寫入模式
buffer.clear();
//簡單關閉即可
dChannel.close();

至此,幾種通道基本用法就介紹完畢了,如果不過癮是因為沒有結(jié)合Selector來講,結(jié)合Selector才是最知識盛宴。在Selector中將結(jié)合Channel和Buffer全面進行介紹。文章來源地址http://www.zghlxwxcb.cn/news/detail-809213.html

到了這里,關于Java-NIO篇章(3)——Channel通道類詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • Java NIO (三)NIO Channel類

    Java NIO (三)NIO Channel類

    ? ? ? ? 前面提到,Java NIO中一個socket連接使用一個Channel來表示。從更廣泛的層面來說,一個通道可以表示一個底層的文件描述符,例如硬件設備、文件、網(wǎng)絡連接等。然而,遠不止如此,Java NIO的通道可以更加細化。例如,不同的網(wǎng)絡傳輸協(xié)議,在Java中都有不同的NIO Chann

    2024年01月18日
    瀏覽(47)
  • channel通道詳解~Go進階

    通道可以被認為是Goroutines通信的管道。類似于管道中的水從一端到另一端的流動,數(shù)據(jù)可以從一端發(fā)送到另一端,通過通道接收。 在前面講Go語言的并發(fā)時候,我們就說過,當多個Goroutine想實現(xiàn)共享數(shù)據(jù)的時候,雖然也提供了傳統(tǒng)的同步機制,但是Go語言強烈建議的是使用

    2024年02月12日
    瀏覽(18)
  • Java NIO原理 (Selector、Channel、Buffer、零拷貝、IO多路復用)

    Java NIO原理 (Selector、Channel、Buffer、零拷貝、IO多路復用)

    系列文章目錄和關于我 最近有很多想學的,像netty的使用、原理源碼,但是苦于自己對于操作系統(tǒng)和nio了解不多,有點無從下手,遂學習之。 上圖粗略描述了網(wǎng)絡io的過程,了解其中的拷貝過程有利于我們理解非阻塞io,以及IO多路復用的必要性。 數(shù)據(jù)從網(wǎng)卡到內(nèi)核緩沖區(qū) 網(wǎng)

    2024年02月08日
    瀏覽(20)
  • 創(chuàng)建應用通道失敗: create channel failed: create channel failed:

    創(chuàng)建應用通道失敗: create channel failed: create channel failed: SendEnvelope failed: calling orderer ‘localhost:7050’ failed: Orderer Client Status Code: (2) CONNECTION_FAILED. Description: dialing connection on target [localhost:7050]: connection is in TRANSIENT_FAILURE 這個錯誤通常是因為客戶端無法連接到Orderer節(jié)點導致的。一

    2024年02月03日
    瀏覽(18)
  • Go語言入門14(channel通道01)

    ?channel用于goroutines之間的通信,讓它們之間可以進行數(shù)據(jù)交換。像管道一樣,一個goroutine_A向channel_A中放數(shù)據(jù),另一個goroutine_B從channel_A取數(shù)據(jù) ?沒有緩沖的通道,如果routine A向通道中發(fā)送了一個數(shù)據(jù),那么必須等到這個數(shù)據(jù)被其他routine 取出之后,才能繼續(xù)往通道里發(fā)送,

    2024年02月02日
    瀏覽(22)
  • muduo網(wǎng)絡庫剖析——通道Channel類

    muduo網(wǎng)絡庫剖析——通道Channel類

    作為一個宏大的、功能健全的muduo庫,考慮的肯定是眾多情況是否可以高效滿足;而作為學習者,我們需要抽取其中的精華進行簡要實現(xiàn),這要求我們足夠了解muduo庫。 做項目 = 模仿 + 修改,不要擔心自己學了也不會寫怎么辦,重要的是積累,學到了這些方法,如果下次在遇

    2024年01月17日
    瀏覽(30)
  • 【Rust 基礎篇】Rust 通道(Channel)

    在 Rust 中,通道(Channel)是一種用于在多個線程之間傳遞數(shù)據(jù)的并發(fā)原語。通道提供了一種安全且高效的方式,允許線程之間進行通信和同步。本篇博客將詳細介紹 Rust 中通道的使用方法,包含代碼示例和對定義的詳細解釋。 在 Rust 中,我們可以使用 std::sync::mpsc 模塊提供的

    2024年02月15日
    瀏覽(50)
  • Java NIO 詳解

    Java NIO 詳解

    一、NIO簡介 NIO 是 Java SE 1.4 引入的一組新的 I/O 相關的 API,它提供了非阻塞式 I/O、選擇器、通道、緩沖區(qū)等新的概念和機制。相比與傳統(tǒng)的 I/O 多出的 N 不是單純的 New,更多的是代表了 Non-blocking 非阻塞,NIO具有更高的并發(fā)性、可擴展性以及更少的資源消耗等優(yōu)點。 二、NI

    2024年04月12日
    瀏覽(23)
  • JAVA NIO概念詳解

    Java NIO(New I/O)是Java平臺提供的一組用于高效處理I/O操作的API。相較于傳統(tǒng)的Java I/O(java.io)API,Java NIO提供了更加靈活、高效的非阻塞I/O操作方式。主要一些概念如下。 Java NIO中的I/O操作是基于緩沖區(qū)的。緩沖區(qū)實質(zhì)上是一個固定大小的內(nèi)存塊,用于存儲數(shù)據(jù)。它可以作為

    2024年02月09日
    瀏覽(37)
  • 【JAVA基礎】- 同步非阻塞模式NIO詳解

    【JAVA基礎】- 同步非阻塞模式NIO詳解

    NIO(Non-Blocking IO)是同步非阻塞方式來處理IO數(shù)據(jù)。服務器實現(xiàn)模式為一個請求一個線程,即客戶端發(fā)送的鏈接請求都會注冊到選擇器上,選擇器輪詢到連接有IO請求時才啟動一個線程進行處理。 同步(synchronous) :調(diào)用方式指應用(Application),調(diào)用方發(fā)起有一個功能調(diào)用時,在

    2024年02月13日
    瀏覽(28)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包