笔记:Java Socket

1.阻塞式


服务器端:
   
    ServerSocketserverSocket = new ServerSocket(8888,10);
    while(true)
    {
          Socket  socket= serverSocket. accept();
        Inpustream inpustream =socket.getInpustream();
      Outpustream outpustream = socket.getOutpustream();
        。。。。。
        socket.close();
   

客户端:
    Sockt socket = newSocket("10.1.2.11",8888);
    Inpustream inpustream =socket.getInpustream();
   Outpustream outpustream = socket.getOutpustream();
    。。。。。
    socket.close();

发生阻塞的地方:
客户端:
(1)请求与服务器建立连接时,执行connect方法,进入阻塞状态,直到连接成功
(2)从输入流读入数据,若无足够数据,进入阻塞,直到读到足够数据或到达末尾
(3)向输出流写数据,直到写完
(4)设置了关闭延迟时间,关闭后阻塞

服务器端:
(1)执行accept方法,等待客户端连接,进入阻塞,直到收到连接
(2)输入流读取数据,若没有足够数据,阻塞
(3)输出流写数据,进入阻塞,直到写完

多线程处理阻塞的局限
(1)线程多,开销大,增加JVM调度线程的负担,增加死锁可能性
(2)线程许多时间浪费在I/O上

2.非阻塞

服务器端:

Selector selector = Selector .open();
ServerSocketChannel serverSocketChannel =ServerSocketChannel. open();
serverSocketChannel. socket().setReuseAddress(true);
serverSocketChannel. configureBlocking(false);
serverSocketChannel. socket(). bind(newInetSocketAddress(8888));
serverSocketChannel. register(selector,SelectionKey. OP_ACCEPT);

while (selector. select() > 0) {
      Set<<b>SelectionKey>selectedKeys = selector. selectedKeys();
      Iterator iterator =selectedKeys.iterator();
      while(iterator.hasNext()) {
          SelectionKey key =null;
          try {
              key = iterator.next();
              if (key. isAcceptable()) {
               accept(key, selector);
              } else if (key. isReadable()) {
               receive(key);
              } else if (key. isWritable()) {
                  send(key);
              }
              iterator.remove();
            } catch(Exception ex) {
                if (key != null) {
                  try{
                        key.cancel();
                        key.channel().close();
                    } catch (Exception ex2) {}
                  }
              }
          }
        }

  protected void accept(SelectionKey key, Selector selector) throws IOException {
        ServerSocketChannel serverSocketChannel =(ServerSocketChannel) key. channel();
        SocketChannel socketChannel =serverSocketChannel. accept();
        socketChannel. configureBlocking(false);
        ByteBuffer buffer =ByteBuffer. allocate(1024);
        socketChannel. register(selector,SelectionKey. OP_READ | SelectionKey. OP_WRITE, buffer);
    }

    protected voidreceive(SelectionKey key) throws IOException {
        ByteBuffer buffer = (ByteBuffer)key. attachment();
        SocketChannel channel = (SocketChannel)key. channel();
        ByteBuffer readBuffer =ByteBuffer.allocate(32);
        channel. read(readBuffer);
        readBuffer.flip();
        buffer.limit(buffer.capacity());
        buffer.put(readBuffer);//
        System.out.println(Charset.forName("UTF-8"). decode(readBuffer).toString());

    }

protected void send(SelectionKey key) throws IOException{
        ByteBuffer buffer = (ByteBuffer)key. attachment();
        SocketChannel channel = (SocketChannel)key. channel();
        buffer.flip();
        String data =Charset.forName("UTF-8").decode(buffer).toString();
        if (data.indexOf("\r\n") == -1) {
            return;
        }
        String str = data.substring(0,data.indexOf("\n") + 1);
        ByteBuffer outBuffer =Charset.forName("UTF-8"). encode(" encode: " + str);
        while (outBuffer. hasRemaining()) {
            channel. write(outBuffer);
        }
        buffer.position(Charset.forName("UTF-8").encode(str).limit());
        buffer.compact();
        if ("bye\r\n".equals(str)) {
            key. cancel();
            key.channel(). close();
            System.out.println(" close connection ");
        }

    }


客户端:
Selector selector=  Selector .open();
SocketChannel socketChannel= SocketChannel. open();
InetSocketAddress address = newInetSocketAddress(InetAddress.getLocalHost(), 8888);
socketChannel. connect(address);
socketChannel. configureBlocking(false);
socketChannel. register(selector,  SelectionKey. OP_READ  |SelectionKey. OP_WRITE);

while (selector. select() > 0) {
      Set<<b>SelectionKey>selectedKeys = selector. selectedKeys();
      Iterator iterator =selectedKeys.iterator();
      while(iterator.hasNext()) {
          SelectionKey key =null;
          try {
              key = iterator.next();
              if (key. isReadable()) {
               receive(key);
              } else if (key. isWritable()) {
                   send(key);
              }
              iterator.remove();
            } catch(Exception ex) {
                if (key != null) {
                  try{
                        key.cancel();
                        key.channel().close();
                    } catch (Exception ex2) {}
                  }
              }
          }
        }

3.非阻塞方式提升性能方式

java.nio.Buffer 缓冲区提升I/O
(1)减少实际物理读写次数
(2)缓冲区内存复用,减少动态分配与回收次数
主要方法:
clear()   将极限设置为容量,位置置0
flip()   将极限设置为位置,位置置0
rewind() 极限不变,位置置0
(也就是说,改变的都是极限,位置都置0)

Selector 轮询方式:
(1)线程接收客户连接时,若无连接,则立即返回
(2)线程从输入流读取数据时,若无足够数据,读取现有数据,立即返回
(3)输出类似

混用非阻塞和多线程:一个线程用于接收连接,另一个线程用于读取数据和发送数据


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值