`
kingxss
  • 浏览: 972997 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java Socket学习笔记(四)- NIO TCP实践

阅读更多

一、回传协议接口和TCP方式实现:

1.接口:

import java.nio.channels.SelectionKey;
import java.io.IOException;

public interface EchoProtocol {
  void handleAccept(SelectionKey key) throws IOException;
  void handleRead(SelectionKey key) throws IOException;
  void handleWrite(SelectionKey key) throws IOException;
}

 2.实现:

import java.nio.channels.*;
import java.nio.ByteBuffer;
import java.io.IOException;

public class TCPEchoSelectorProtocol implements EchoProtocol{
    private int bufSize; // Size of I/O buffer

    public EchoSelectorProtocol(int bufSize) {
        this.bufSize = bufSize;
    }

    public void handleAccept(SelectionKey key) throws IOException {
        SocketChannel clntChan = ((ServerSocketChannel) key.channel()).accept();
        clntChan.configureBlocking(false); // Must be nonblocking to register
        // Register the selector with new channel for read and attach byte buffer
        clntChan.register(key.selector(), SelectionKey.OP_READ, ByteBuffer.allocate(bufSize));
        
    }

    public void handleRead(SelectionKey key) throws IOException {
        // Client socket channel has pending data
        SocketChannel clntChan = (SocketChannel) key.channel();
        ByteBuffer buf = (ByteBuffer) key.attachment();
        long bytesRead = clntChan.read(buf);
        if (bytesRead == -1) { // Did the other end close?
            clntChan.close();
        } else if (bytesRead > 0) {
            // Indicate via key that reading/writing are both of interest now.
            key.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE);
        }
    }

    public void handleWrite(SelectionKey key) throws IOException {
        /*
         * Channel is available for writing, and key is valid (i.e., client channel 
         * not closed).
         */
        // Retrieve data read earlier
        ByteBuffer buf = (ByteBuffer) key.attachment();
        buf.flip(); // Prepare buffer for writing
        SocketChannel clntChan = (SocketChannel) key.channel();
        clntChan.write(buf);
        if (!buf.hasRemaining()) { // Buffer completely written? 
            //Nothing left, so no longer interested in writes
            key.interestOps(SelectionKey.OP_READ);
        }
        buf.compact(); // Make room for more data to be read in
    }

}

 

二、NIO TCP客户端:

import java.net.InetSocketAddress;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class TCPEchoClientNonblocking {

    public static void main(String args[]) throws Exception {
        String server = "127.0.0.1"; // Server name or IP address
        // Convert input String to bytes using the default charset
        byte[] argument = "0123456789abcdefghijklmnopqrstuvwxyz".getBytes();

        int servPort = 5500;

        // Create channel and set to nonblocking
        SocketChannel clntChan = SocketChannel.open();
        clntChan.configureBlocking(false);

        // Initiate connection to server and repeatedly poll until complete
        if (!clntChan.connect(new InetSocketAddress(server, servPort))) {
            while (!clntChan.finishConnect()) {
                System.out.print("."); // Do something else
            }
        }
        ByteBuffer writeBuf = ByteBuffer.wrap(argument);
        ByteBuffer readBuf = ByteBuffer.allocate(argument.length);
        int totalBytesRcvd = 0; // Total bytes received so far
        int bytesRcvd; // Bytes received in last read
        while (totalBytesRcvd < argument.length) {
            if (writeBuf.hasRemaining()) {
                clntChan.write(writeBuf);
            }
            if ((bytesRcvd = clntChan.read(readBuf)) == -1) {
                throw new SocketException("Connection closed prematurely");
            }
            totalBytesRcvd += bytesRcvd;
            System.out.print("."); // Do something else
        }

        System.out.println("Received: " + // convert to String per default charset
                new String(readBuf.array(), 0, totalBytesRcvd).length());
        clntChan.close();
    }
}

 

三、NIO TCP服务端:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.*;
import java.util.Iterator;

public class TCPServerSelector {
    private static final int BUFSIZE = 256; // Buffer size (bytes)
    private static final int TIMEOUT = 3000; // Wait timeout (milliseconds)
    
    public static void main(String[] args) throws IOException {
        int[] ports = {5500};
        // Create a selector to multiplex listening sockets and connections
        Selector selector = Selector.open();

        // Create listening socket channel for each port and register selector
        for (int port : ports) {
            ServerSocketChannel listnChannel = ServerSocketChannel.open();
            listnChannel.socket().bind(new InetSocketAddress(port));
            listnChannel.configureBlocking(false); // must be nonblocking to register
            // Register selector with channel. The returned key is ignored
            listnChannel.register(selector, SelectionKey.OP_ACCEPT);
        }

        // Create a handler that will implement the protocol
        TCPProtocol protocol = new TCPEchoSelectorProtocol(BUFSIZE);

        while (true) { // Run forever, processing available I/O operations
            // Wait for some channel to be ready (or timeout)
            if (selector.select(TIMEOUT) == 0) { // returns # of ready chans
                System.out.print(".");
                continue;
            }

            // Get iterator on set of keys with I/O to process
            Iterator<SelectionKey> keyIter = selector.selectedKeys().iterator();
            while (keyIter.hasNext()) {
                SelectionKey key = keyIter.next(); // Key is bit mask
                // Server socket channel has pending connection requests?
                if (key.isAcceptable()) {
                    System.out.println("----accept-----");
                    protocol.handleAccept(key);
                }
                // Client socket channel has pending data?
                if (key.isReadable()) {
                    System.out.println("----read-----");
                    protocol.handleRead(key);
                }
                // Client socket channel is available for writing and 
                // key is valid (i.e., channel not closed)?
                if (key.isValid() && key.isWritable()) {
                    System.out.println("----write-----");
                    protocol.handleWrite(key);
                }
                keyIter.remove(); // remove from set of selected keys
            }
        }
    }
    
}

 

 

 参考:

1.《Java TCP/IP Socket编程(原书第2版)》

分享到:
评论

相关推荐

    [Java学习笔记doc]-javase基本知识

    **Java学习笔记——Java SE基本知识** Java是一种广泛使用的面向对象的编程语言,以其跨平台、安全性高和可移植性而闻名。Java Standard Edition(Java SE)是Java平台的基础,它提供了开发和运行桌面应用程序、...

    2022年Java学习笔记-Java课程配套案例.rar

    这份"2022年Java学习笔记-Java课程配套案例.rar"压缩包文件显然是为了帮助学习者深入理解Java编程,通过实践案例来巩固理论知识。下面将详细探讨Java语言的一些核心知识点,并结合压缩包中的案例进行说明。 1. **...

    JAVA学习笔记 林信良

    《JAVA学习笔记》是林信良先生的一部深入浅出的Java编程教程,旨在帮助初学者和有一定经验的开发者巩固和提升Java编程技能。这本书涵盖了Java语言的基础到高级概念,是一份宝贵的自学资料。 首先,从基础部分开始,...

    JAVA学习笔记

    文件“2013-12-26-java-newIO.txt”和“2013-12-27-java-newIO续.txt”应该会详细阐述NIO的工作原理和实际应用。 此外,其他文件如“2013-12-28-java-运行时信息.txt”可能涉及运行时环境的监控和调试技巧,“2013-...

    java学习笔记-老师的课程笔记

    Java学习笔记是初学者探索Java编程世界的宝贵资源。这份由老师精心整理的课程笔记涵盖了Java的基础到进阶知识,旨在帮助新手快速理解并掌握这门强大的面向对象编程语言。笔记内容可能包括但不限于以下方面: 一、...

    java学习笔记之大鹏JAVA终级总结

    Java学习笔记之大鹏JAVA终级总结,是针对Java编程语言深入学习和面试准备的一份综合资料。这份总结涵盖了从基础知识到高级概念的多个方面,旨在帮助初学者理解和掌握Java的核心概念,同时解决面试中可能出现的关键...

    Java学习超强笔记

    以上只是Java学习笔记中可能涉及的部分知识点,实际上,完整的笔记还会包含更深入的Java特性,如注解、模块系统、JDBC数据库访问、Spring框架等内容,以及实际项目开发中的最佳实践。这份笔记是初级Java程序员系统...

    Java 客户端服务器程序 学习笔记

    通过阅读这篇学习笔记,你可以掌握Java客户端服务器编程的基本概念和实践技巧,并能够开发自己的网络应用程序。记住,实践是最好的老师,所以动手尝试创建一个简单的客户端服务器应用程序是巩固理论知识的绝佳方法。

    网络编程-狂神说Java学习笔记

    "狂神说Java学习笔记"提供了深入理解和实践网络编程的宝贵资源。本笔记主要涵盖了以下几个关键知识点: 1. **Java网络编程基础**:Java通过Socket API提供了网络通信的能力。Socket代表了网络上的两个应用程序之间...

    Java-J2SE学习笔记

    Java-J2SE(Java Standard Edition)是...以上内容仅是Java-J2SE学习笔记可能涉及的部分主题,实际笔记可能会更详细,包括更多的示例代码和实践案例。通过深入学习这些知识点,开发者可以构建功能丰富的Java应用程序。

    Java公司培训经典学习笔记

    Java公司培训经典学习笔记是针对Java编程语言进行深入学习的一份宝贵资料,涵盖了从基础到高级的诸多知识点,旨在帮助开发者提升技能,适应企业级项目开发的需求。以下将详细阐述这些笔记中的关键点: 1. **Java...

    java基础学习笔记

    Java提供了丰富的API用于网络通信,如Socket和ServerSocket类用于TCP连接,DatagramSocket和DatagramPacket类用于UDP通信。 十、Java Swing和JavaFX(GUI编程) Swing是Java AWT(Abstract Window Toolkit)的扩展...

    java全套笔记 来自狂神说java笔录.zip

    11. **Java IO/NIO**:深入理解流的分类,学习非阻塞I/O模型NIO(New Input/Output)。 12. **Java 8及更高版本新特性**:包括Lambda表达式、Stream API、Optional类、日期时间API的改进等。 这些笔记内容全面覆盖...

    java源码笔记

    - Socket编程:TCP和UDP协议,理解Socket类和ServerSocket类在客户端和服务器端的应用。 - URL与HTTP:如何使用URL和URLConnection类进行HTTP请求。 - NIO(非阻塞I/O):Java提供的高效I/O模型,用于提高网络...

    Java+JDK6学习笔记

    8. **网络编程**:学习Java的Socket编程,包括TCP和UDP通信,以及ServerSocket和Socket类的使用。 9. **Swing GUI**:JDK6对Swing组件进行了优化,可以创建丰富的图形用户界面。学习JFrame、JButton、JLabel、...

    Java随堂笔记

    Java是一种广泛使用的面向对象的编程语言,以其跨平台、...以上知识点构成了Java编程的核心部分,通过深入学习和实践,你可以逐步掌握企业级Java开发所需技能。这份“Java随堂笔记”正是你踏上这一旅程的重要参考资料。

    Java架构面试专题(含答案)和学习笔记-1

    本资料包含学习笔记和答案,便于自我检验和理解。 1. **Java基础知识**: - **内存管理**:包括垃圾回收机制、内存泄漏及其检测方法、JVM内存模型(堆、栈、方法区等)。 - **数据类型与数据结构**:深入理解原始...

    Java 基础 第3阶段:高级应用-尚硅谷学习笔记(含面试题) 2023年

    在这个阶段的学习中,尚硅谷提供了2023年的学习笔记和面试题,帮助你提升Java技能并为求职做好准备。 首先,多线程是Java的一个关键特性,允许程序同时执行多个任务。理解线程的创建(通过Thread类或实现Runnable...

    java笔记 java笔记 java笔记

    这份"java笔记"涵盖了从基础到进阶的各种Java知识,旨在帮助学习者系统地掌握这门语言。以下是对笔记内容的详细解读: 1. **Java基础知识**: - **语法特性**:Java遵循C++的语法结构,但更加简洁和安全,如自动...

    java基础18天Typora笔记

    通过这份笔记,学习者将逐步了解并掌握Java语言的核心概念和基本语法,为后续的深入学习和实践打下坚实的基础。 1. **Java简介** Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems(现为Oracle公司)...

Global site tag (gtag.js) - Google Analytics