日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

java nio非阻塞式网络通信入门案例 (nio服务端与bio多线程客户端(java/python)

發布時間:2024/9/30 python 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java nio非阻塞式网络通信入门案例 (nio服务端与bio多线程客户端(java/python) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

    • nio服務端:
    • 改進服務端
    • java客戶端
    • python版本客戶端:
    • python客戶端改進版(多線程執行)

注意:如果想把服務端程序放在自己的服務器上,要記得開放相應的端口,否則客戶端會顯示連接超時。socket的ip地址改為公網ip,

nio服務端:

/*** @Author* @Description 學習selector* @Date**/ public class select {public void getSelector() throws IOException {//創建 SelectorSelector selector = Selector.open();//用open方法創建ServerSocketChannel channel = ServerSocketChannel.open();//獲取通道channel.configureBlocking(false);//切換為非阻塞模式channel.bind(new InetSocketAddress(9999));channel.register(selector, SelectionKey.OP_ACCEPT);//注冊通道到選擇器上,第二個參數為指定的事件為”監聽接收事件“ // // * 讀 : SelectionKey.OP_READ (1) //* 寫 : SelectionKey.OP_WRITE (4) //* 連接 : SelectionKey.OP_CONNECT (8) //* 接收 : SelectionKey.OP_ACCEPT (16) //* 若注冊時不止監聽一個事件,則可以使用“位或”操作符連接。//輪詢式的獲取選擇器上已經“準備就緒”的事件while (selector.select() > 0) {System.out.println("開始");//7. 獲取當前選擇器中所有注冊的“選擇鍵(已就緒的監聽事件)”Iterator<SelectionKey> it = selector.selectedKeys().iterator();while (it.hasNext()) {//8. 獲取準備“就緒”的是事件SelectionKey sk = it.next();//9. 判斷具體是什么事件準備就緒if (sk.isAcceptable()) {//10. 若“接收就緒”,獲取客戶端連接SocketChannel sChannel = channel.accept();//11. 切換非阻塞模式sChannel.configureBlocking(false);//12. 將該通道注冊到選擇器上sChannel.register(selector, SelectionKey.OP_READ);} else if (sk.isReadable()) {//13. 獲取當前選擇器上“讀就緒”狀態的通道SocketChannel sChannel = (SocketChannel) sk.channel();//14. 讀取數據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();} }

改進服務端

加一個catch ioexception,防止因為客戶端關閉連接導致服務端也異常終止
主要邏輯在讀取數據的函數 readData(sk);中,其他部分跟上面一樣

while (selector.select() > 0) {// System.out.println("開始:");//7. 獲取當前選擇器中所有注冊的“選擇鍵(已就緒的監聽事件)”Iterator<SelectionKey> it = selector.selectedKeys().iterator();while (it.hasNext()) {//8. 獲取準備“就緒”的是事件SelectionKey sk = it.next();//9. 判斷具體是什么事件準備就緒if (sk.isAcceptable()) {// 10. 若“接收就緒”,獲取客戶端連接SocketChannel sChannel = channel.accept();//11. 切換非阻塞模式sChannel.configureBlocking(false);//12. 將該通道注冊到選擇器上sChannel.register(selector, SelectionKey.OP_READ);} else if (sk.isReadable()) {readData(sk);//15. 取消選擇鍵 SelectionKey}it.remove();}}}//讀取客戶端消息private void readData (SelectionKey key){//取到關聯的channleSocketChannel channel = null;try {//得到channelchannel = (SocketChannel) key.channel();//創建bufferByteBuffer buffer = ByteBuffer.allocate(1024);int count = channel.read(buffer);//根據count的值做處理if (count > 0) {//把緩存區的數據轉成字符串String msg = new String(buffer.array());//輸出該消息System.out.println("form 客戶端: " + msg);//向其它的客戶端轉發消息(去掉自己), 專門寫一個方法來處理// sendInfoToOtherClients(msg, channel);}else {System.out.println("no dara");}} catch (IOException e) {try {System.out.println(channel.getRemoteAddress() + " 離線了..");e.printStackTrace();//取消注冊key.cancel();//關閉通道channel.close();} catch (IOException e2) {e2.printStackTrace();;}}}

這樣的話會發現即使服務端發生io異常也仍然未終止程序,有新的客戶端連接時還可以繼續正常運行

java客戶端

客戶端模擬多線程發送socket數據:

/*** @Author* @Description 多線程bio讀寫數據* @Date**/public class mutiClient {public static void main(String[] args) throws InterruptedException {// 接下來模擬3個Client并發訪問服務器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;// 若每一個Client都保持使用BIO方式發送數據到Server,并讀取數據。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讀取數據線程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寫數據線程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);

運行服務端再運行客戶端,j結果:

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()

結果:

python客戶端改進版(多線程執行)

注意:寫sleep是因為防止主線程結束了導致多線程沒有執行而失效

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("無法啟動線程")time.sleep(5)

服務端:

總結

以上是生活随笔為你收集整理的java nio非阻塞式网络通信入门案例 (nio服务端与bio多线程客户端(java/python)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。