Java NIO 網絡編程基礎


Java NIO提供了一套網絡api,可以用來處理連接數很多的情況。他的基本思想就是用一個線程來處理多個channel。
nio selector

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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package geym.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class MyServer {
    public static void main(String args[]throws Exception  
    {  
        MyServer server new MyServer(8080);  
        server.listen();  
    }  
  
    // 接受和發送數據緩沖區  
    private ByteBuffer send = ByteBuffer.allocate(1024);  
    private ByteBuffer receive = ByteBuffer.allocate(1024);  
  
    public int port 0;  
  
    ServerSocketChannel ssc null;  
  
    Selector selector null;  
  
    public MyServer(int portthrows Exception  
    {  
        // 打開服務器套接字通道  
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();  
        // 服務器配置為非阻塞  
        serverSocketChannel.configureBlocking(false);  
        // 檢索與此通道關聯的服務器套接字  
        ServerSocket serverSocket = serverSocketChannel.socket();  
        // 套接字的地址端口綁定
        serverSocket.bind(new InetSocketAddress(port));  
        // 通過open()方法找到Selector  
        selector = Selector.open();  
  
        // 注冊到selector,等待連接  
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);  
        System.out.println("Server Start----8888:");  
          
        // 向發送緩沖區加入數據  
        send.put("data come from server".getBytes());  
    }  
  
    // 監聽  
    private void listen(throws IOException  
    {  
        while (true)  
        {  
            // 等待一個連接,可能會返回多個key
            int count=selector.select();
            System.out.println("count="+count);
            // 返回此選擇器的已選擇鍵集。  
            Set<SelectionKey> selectionKeys = selector.selectedKeys();  
            Iterator<SelectionKey> iterator = selectionKeys.iterator();  
            while (iterator.hasNext())  
            {  
                SelectionKey selectionKey = iterator.next();  
  
                // 這里記得手動的把他remove掉,不然selector中的selectedKeys集合不會自動去除  
                iterator.remove();  
                handle(selectionKey);  
            }  
        }  
    }  
  
    // 處理請求  
    private void handle(SelectionKey selectionKeythrows IOException  
    {  
  
        ServerSocketChannel server null;  
        SocketChannel client null;  
        String receiveText;  
        String sendText;  
        int count 0;  
  
        // 測試此鍵的通道是否已准備好接受新的套接字連接。  
        if (selectionKey.isAcceptable())  
        {  
            System.out.println("selectionKey.isAcceptable()");
            // 返回為之創建此鍵的通道。  
            server (ServerSocketChannel) selectionKey.channel();  
  
            // 此方法返回的套接字通道(如果有)將處於阻塞模式。  
            client = server.accept();  
            // 配置為非阻塞  
            client.configureBlocking(false);  
            // 注冊到selector,等待連接  
            client.register(selector, SelectionKey.OP_READ  
                    | SelectionKey.OP_WRITE);  
        }  
        else  
            if (selectionKey.isReadable())  
            {  
                System.out.println("selectionKey.isReadable()");
                // 返回為之創建此鍵的通道。  
                client (SocketChannel) selectionKey.channel();  
                // 將緩沖區清空以備下次讀取  
                receive.clear();  
                // 讀取服務器發送來的數據到緩沖區中  
                client.read(receive);  
  
//                System.out.println(new String(receive.array()));  
                  
                selectionKey.interestOps(SelectionKey.OP_WRITE);  
            }  
            else  
                if (selectionKey.isWritable())  
                {  
                    System.out.println("selectionKey.isWritable()");
                    // 將緩沖區清空以備下次寫入  
                    send.flip();  
                    // 返回為之創建此鍵的通道。  
                    client (SocketChannel) selectionKey.channel();  
  
                    // 輸出到通道  
                    client.write(send);  
                      
//                    selectionKey.interestOps(SelectionKey.OP_READ);  
                }  
    
}

客戶端代碼如下:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM