Java网络编程之非阻塞I/O客户端TCP实例

 非阻塞I/O可以减少服务器无用的等待,从而高效的处理其他工作。能够让一个线程负责多个连接,而不是为每一个Socket都分配一个连接,在该线程中,选取负责多个连接中的一个已经准备好接收数据的连接,从而尽快的用数据进行填充,进而转下下一个准备好的连接。

 传统意义上的连接,会每次都会产生大量的线程,线程切换会耗费很大的时间。

 当然非阻塞I/O主要是未服务器端设计的,不过这里是主要模拟一下,论述客户端利用通道和缓冲区的时候的流程。

 在这里实例一个客户端的基于通道和缓冲区的连接。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package com.nio.client;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.SocketChannel;
import java.nio.channels.WritableByteChannel;
public class ChargenClient {
                                       
    private static final int DEFAULT_PORT=19;
                                       
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try{
            SocketAddress address =new InetSocketAddress("localhost",2222);
            //利用给定的主机和端口创建一个通道,此时会自动连接,默认打开的通道是阻塞状态道
            //下一行代码在建立连接之前不会被执行,失败会抛出一个IOException
            SocketChannel client=SocketChannel.open(address);
            //设置该通道未非阻塞状态
            client.configureBlocking(false);
                                               
            //将读取的数据直接写入到通道中,不需要寻找该Socket的输入流
            //但是写入与写出的需要ByteBuffer 对象
            ByteBuffer buffer=ByteBuffer.allocate(80);
                                               
            //这里先构造一个向System.out写入字节的通道
            //但是它不对所得的信道进行缓冲,只是将其 I/O 操作重定向到给定的流
            WritableByteChannel out=Channels.newChannel(System.out);
            //将此buffer对象传递给通道client的read方法,通道会将从
            //socket读取的数据自动的填充到该缓冲区buffer
            //当缓冲区buffer有数据后,就会被复制到System.out
            while(client.read(buffer)!=-1)
            {
                //目的是从缓冲区的开头读取
                buffer.flip();
                out.write(buffer);
                //这里只是将缓冲区重置到初始状态,但是其缓冲区的数据依旧还在,
                //只不过会被新的数据马上覆盖
                buffer.clear();
            }
                                               
            //非阻塞下读取数据方式,
            //由于在非阻塞下,read会至少读取一个字节,当读取不到数据的时候返回0
            while(true)
            {
                int n=client.read(buffer);
                if(n>0)
                {
                    buffer.flip();
                    out.write(buffer);
                    buffer.clear();
                }
                else if( n==-1)
                {
                    break;
                }
            }
                                               
        }catch(IOException e)
        {
            System.out.println(e);
        }
    }
}


上一篇:python实现FTP服务器


下一篇:SPDY简介