zoukankan      html  css  js  c++  java
  • Socket通道

    Socket通道

    socket通道与文件通道有不一样的特征:

    1.socket通道类可以运行与非阻塞模式并且是可选择的,这两个性能可以激活大程序(比如网络服务器和中间件组件)巨大的可伸缩和灵活性,因此,再也没有为每个socket连接使用一个线程的必要了。借助NIO类,一个或者几个线程可以管理成百上千的活动socket连接了,并且只有很少甚至没有性能的损失。

    2.全部socket通道类(DatagramChannel、SocketChannel,ServerSocketChannel)被实例化时都会创建一个对应的socket对象,也就是来自java.net的类(Datagram,socket,serverSocket),这些socket可以通过调用socket()方法从通道类获取,另外,这三个类都有getChannel方法获取通道。

    3.每一个socket通道都有一个关联的socket对象,反之不是。如果直接实例化的方式创建一个socket对象,它就不会有关联的socketChannel,调用它的getChannel方法将总是返回null。

    非阻塞模式

    传统java socket的阻塞性质曾经是java程序可伸缩性的最重要制约之一,非阻塞io是许多复杂的,高性能的程序构建的基础。

    要把一个socket通道置于非阻塞模式,要依赖的是socket通道类的SelectableChannel。

    public abstract class SelectableChannel extends AbstractInterruptibleChannel implements Channel
    {
        ...
        public abstract void configureBlocking(boolean block) throws IOException;
        public abstract boolean isBlocking();
        public abstract Object blockngLock();
        ...
    }

    从该api中可以看出,设置或重新设置一个通道的阻塞模式是很简单的,只要调用configureBlocking方法即可,参数的true为阻塞模式,参数为false设为非阻塞模式。isBloking方式是判断某个socket通道处于哪种模式。偶尔,我们需要防止socket通道的阻塞模式被修改,所以有一个

    blockingLock方法,该方法返回一个非透明对象引用,返回的对象是通道实现修改阻塞模式时内部使用的,只有拥有该对象的锁的线程才可以修改通道的阻塞模式,对于确保在执行代码关键部分时socket通道的阻塞模式不会改变,以及在不影响其他线程的前提下暂时改变阻塞模式来说,

    这个方法是非常方便的。

    服务端

    public static void main(String[] args) throws Exception {
            int port = 9090;
            if (args != null && args.length > 0) {
                port = Integer.parseInt(args[0]);
            }
            ServerSocketChannel ssc = ServerSocketChannel.open();// 打开一个ServerSocketChannel对象。
            ssc.configureBlocking(false);// 设置该通道是非阻塞式的
            ssc.bind(new InetSocketAddress(port));// 绑定端口
            System.out.println("开始等待客户端的数据!时间为" + System.currentTimeMillis());
            while (true) {
                SocketChannel sc = ssc.accept();
                if (sc == null) {
                    // 如果当前没有数据,等待1秒钟再次轮询是否有数据,在学习了Selector之后此处可以使用Selector
                    Thread.sleep(1000);
                } else {
                    System.out.println("客户端已有数据到来,客户端ip为:"
                            + sc.socket().getRemoteSocketAddress() + ", 时间为"
                            + System.currentTimeMillis());
                    ByteBuffer bb = ByteBuffer.allocate(100);// 初始化一个缓冲区
                    sc.read(bb);
                    bb.flip();
                    while (bb.hasRemaining()) {
                        System.out.print((char) bb.get());// get方法一次获取一个字节,然后position往后移动一个位置。
                    }
                    sc.close();
                    System.exit(0);
                }
            }
        }
    

    客户端

    服务端经常会使用非阻塞socket通达,因为它们使同时管理很多socket通道变得更容易,客户端不强求,因为客户端发起的socket操作往往比较少,且都一个个发起的。但是,在客户端使用一个或几个非阻塞模式的socket通道也是有益处的,比如借助非阻塞socket通道,gui程序可以

    专注于用户请求并同时维护与一个或多个服务器的会话。在很多程序上,非阻塞模式都是有用的。

     1 public class EchoClient {
     2     private static final String STR = "Hello World!";
     3     private static final String REMOTE_IP = "127.0.0.1";
     4 
     5     public static void main(String[] args) throws Exception {
     6         int port = 9090;
     7         if (args != null && args.length > 0) {
     8             port = Integer.parseInt(args[0]);
     9         }
    10         SocketChannel sc = SocketChannel.open();
    11         sc.configureBlocking(false);
    12         sc.connect(new InetSocketAddress(REMOTE_IP, port));
    13         while (!sc.finishConnect()) {
    14             System.out.println("同" + REMOTE_IP + "的连接正在建立,请稍等!");
    15             Thread.sleep(10);
    16         }
    17         System.out.println("连接已建立,待写入内容至指定ip+端口!时间为"
    18                 + System.currentTimeMillis());
    19         ByteBuffer bb = ByteBuffer.allocate(STR.length());
    20         bb.put(STR.getBytes());
    21         bb.flip(); // 写缓冲区的数据之前一定要先反转(flip)
    22         sc.write(bb);//会把position到limit的内容写到通道里面,如果没有调用flip,那么就是空。
    23         bb.clear();
    24         sc.close();
    25     }
    26 }
  • 相关阅读:
    2-sat问题,输出方案,几种方法(赵爽的论文染色解法+其完全改进版)浅析 / POJ3683
    hdu 4587 2013南京邀请赛B题/ / 求割点后连通分量数变形。
    最小费用最大流粗解 poj2516
    hdu3078 建层次树+在线LCA算法+排序
    hdu 3594 Cactus /uva 10510 仙人掌图判定
    有向图最小路径覆盖方法浅析、证明 //hdu 3861
    hdu 1827 有向图缩点看度数
    条件转化,2-sat BZOJ 1997
    2-sat基础题 BZOJ 1823
    2-sat 分类讨论 UVALIVE 3713
  • 原文地址:https://www.cnblogs.com/tp123/p/6438936.html
Copyright © 2011-2022 走看看