java nio非阻塞式网络通信入门案例 (nio服务端与bio多线程客户端(java/python)
生活随笔
收集整理的這篇文章主要介紹了
java nio非阻塞式网络通信入门案例 (nio服务端与bio多线程客户端(java/python)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
- nio服務(wù)端:
- 改進(jìn)服務(wù)端
- java客戶端
- python版本客戶端:
- python客戶端改進(jìn)版(多線程執(zhí)行)
注意:如果想把服務(wù)端程序放在自己的服務(wù)器上,要記得開放相應(yīng)的端口,否則客戶端會(huì)顯示連接超時(shí)。socket的ip地址改為公網(wǎng)ip,
nio服務(wù)端:
/*** @Author* @Description 學(xué)習(xí)selector* @Date**/ public class select {public void getSelector() throws IOException {//創(chuàng)建 SelectorSelector selector = Selector.open();//用open方法創(chuàng)建ServerSocketChannel channel = ServerSocketChannel.open();//獲取通道channel.configureBlocking(false);//切換為非阻塞模式channel.bind(new InetSocketAddress(9999));channel.register(selector, SelectionKey.OP_ACCEPT);//注冊(cè)通道到選擇器上,第二個(gè)參數(shù)為指定的事件為”監(jiān)聽接收事件“ // // * 讀 : SelectionKey.OP_READ (1) //* 寫 : SelectionKey.OP_WRITE (4) //* 連接 : SelectionKey.OP_CONNECT (8) //* 接收 : SelectionKey.OP_ACCEPT (16) //* 若注冊(cè)時(shí)不止監(jiān)聽一個(gè)事件,則可以使用“位或”操作符連接。//輪詢式的獲取選擇器上已經(jīng)“準(zhǔn)備就緒”的事件while (selector.select() > 0) {System.out.println("開始");//7. 獲取當(dāng)前選擇器中所有注冊(cè)的“選擇鍵(已就緒的監(jiān)聽事件)”Iterator<SelectionKey> it = selector.selectedKeys().iterator();while (it.hasNext()) {//8. 獲取準(zhǔn)備“就緒”的是事件SelectionKey sk = it.next();//9. 判斷具體是什么事件準(zhǔn)備就緒if (sk.isAcceptable()) {//10. 若“接收就緒”,獲取客戶端連接SocketChannel sChannel = channel.accept();//11. 切換非阻塞模式sChannel.configureBlocking(false);//12. 將該通道注冊(cè)到選擇器上sChannel.register(selector, SelectionKey.OP_READ);} else if (sk.isReadable()) {//13. 獲取當(dāng)前選擇器上“讀就緒”狀態(tài)的通道SocketChannel sChannel = (SocketChannel) sk.channel();//14. 讀取數(shù)據(jù)ByteBuffer buf = ByteBuffer.allocate(1024);int len = 0;while ((len = sChannel.read(buf)) > 0) {buf.flip();System.out.println(new String(buf.array(), 0, len));buf.clear();}}//15. 取消選擇鍵 SelectionKeyit.remove();}}}public static void main(String[] args) throws IOException {new select().getSelector();} }改進(jìn)服務(wù)端
加一個(gè)catch ioexception,防止因?yàn)榭蛻舳岁P(guān)閉連接導(dǎo)致服務(wù)端也異常終止
主要邏輯在讀取數(shù)據(jù)的函數(shù) readData(sk);中,其他部分跟上面一樣
這樣的話會(huì)發(fā)現(xiàn)即使服務(wù)端發(fā)生io異常也仍然未終止程序,有新的客戶端連接時(shí)還可以繼續(xù)正常運(yùn)行
java客戶端
客戶端模擬多線程發(fā)送socket數(shù)據(jù):
/*** @Author* @Description 多線程bio讀寫數(shù)據(jù)* @Date**/public class mutiClient {public static void main(String[] args) throws InterruptedException {// 接下來(lái)模擬3個(gè)Client并發(fā)訪問服務(wù)器int poolsize = 3;ExecutorService pool = Executors.newFixedThreadPool(poolsize);Collection< Callable<Object>> tasks =new ArrayList<>(10);final String clientname="clientThread";for (int i = 0; i < poolsize; i++) {final int n = i;// 若每一個(gè)Client都保持使用BIO方式發(fā)送數(shù)據(jù)到Server,并讀取數(shù)據(jù)。tasks.add(new Callable() {@Overridepublic Object call() throws Exception {Socket socket = new Socket("127.0.0.1", 9999);final InputStream input = socket.getInputStream();final OutputStream out = socket.getOutputStream();final String clientname_n = clientname + "_" + n;// BIO讀取數(shù)據(jù)線程new Thread(clientname_n + "_read") {@Overridepublic void run() {byte[] bs = new byte[1024];while (true) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}int len = 0;try {while ((len = input.read(bs)) != -1) {System.out.println("Clinet thread " + Thread.currentThread().getName() + " read: " + new String(bs, 0, len));}} catch (IOException e) {e.printStackTrace();}}}}.start();// BIO寫數(shù)據(jù)線程new Thread(clientname_n + "_write") {@Overridepublic void run() {int a = 0;while (true) {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}String str = Thread.currentThread().getName()+ " hello, " + a;try {out.write(str.getBytes());a++;} catch (IOException e) {e.printStackTrace();}}}}.start();return null;}});} pool.invokeAll(tasks);運(yùn)行服務(wù)端再運(yùn)行客戶端,j結(jié)果:
python版本客戶端:
from socket import * host='localhost' port=9999 bufsize=1024 addr=(host,port) tcpClient=socket(AF_INET,SOCK_STREAM) tcpClient.connect(addr) while True:data=input('>')if not data:breaktcpClient.send(str.encode(data))data=tcpClient.recv(bufsize)if not data:continueprint(data) tcpClient.close()結(jié)果:
python客戶端改進(jìn)版(多線程執(zhí)行)
注意:寫sleep是因?yàn)榉乐怪骶€程結(jié)束了導(dǎo)致多線程沒有執(zhí)行而失效
def tcpcilent(threadName,port):host = 'localhost'bufsize = 1024port=9999addr = (host, port)tcpClient = socket(AF_INET, SOCK_STREAM)tcpClient.connect(addr)i =0#tcpClient.setblocking(0)while True:tcpClient.send(str.encode(threadName+"uiyuiyiu"+'\n'))time.sleep(1)if i>100:breaktcpClient.close() if __name__ == '__main__':try:_thread.start_new_thread(tcpcilent, ("thread1", 9999,))_thread.start_new_thread(tcpcilent, ("thread2", 9999,))except:print("無(wú)法啟動(dòng)線程")time.sleep(5)服務(wù)端:
總結(jié)
以上是生活随笔為你收集整理的java nio非阻塞式网络通信入门案例 (nio服务端与bio多线程客户端(java/python)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: springboot+thymeleaf
- 下一篇: shell读取文件到变量、管道重定向、i