最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Socket編程簡單示例(聊天服務器)

 更新時間:2023年02月18日 14:15:14   作者:念念清晰  
socket編程是在不同的進程間進行網(wǎng)絡通訊的一種協(xié)議,下面這篇文章主要給大家介紹了關于Socket編程簡單示例的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下

傳統(tǒng)Socket基于BIO實現(xiàn)一個簡單的聊天服務器

服務端代碼如下

public class MyServerSocket {
  public static void main(String[] args) throws IOException {
    ServerSocket serverSocket = new ServerSocket();
    // 綁定5000端口
    serverSocket.bind(new InetSocketAddress("127.0.0.1", 5000));
    System.out.println("服務端啟動成功...");
    while (true) {
      // 如果獲取不到socket就會一致阻塞在此
      Socket socket = serverSocket.accept();
      InputStream is = socket.getInputStream();
      byte[] buf = new byte[1024];
      int len = is.read(buf);
      System.out.println("客戶端說:" + new String(buf, 0, len, StandardCharsets.UTF_8));
      OutputStream os = socket.getOutputStream();
      os.write("你好客戶端,我收到你的消息了".getBytes(StandardCharsets.UTF_8));
    }
  }
}

客戶端代碼如下

public class ClientSocket {
  public static void main(String[] args) throws IOException {
    Socket socket = new Socket();
    socket.connect(new InetSocketAddress("127.0.0.1",5000));
    OutputStream os = socket.getOutputStream();
    os.write("hello服務端~".getBytes(StandardCharsets.UTF_8));
    InputStream is = socket.getInputStream();
    byte[] buf = new byte[1024];
    int len = is.read(buf);
    System.out.println("服務器說:" + new String(buf, 0, len, StandardCharsets.UTF_8));
  }
}

先啟動服務器端,再啟動客戶端。即可

傳統(tǒng)BIO是阻塞的,舉個燒水的例子來理解

Socket編寫一個簡單的Http服務器

http服務器的代碼

public class HttpServer {
  private static String response = """
      HTTP/1.1 200 OK
      content-type: text/html
            
      <h1>hello,client</h1>
      """;

  public static void main(String[] args) throws IOException {
    ServerSocket serverSocket = new ServerSocket();
    serverSocket.bind(new InetSocketAddress("127.0.0.1", 5001));
    System.out.println("HTTP服務器啟動成功");
    while (true) {
      Socket client = serverSocket.accept();
      // 獲取客戶端發(fā)送過來的數(shù)據(jù)
      InputStream is = client.getInputStream();
      byte[] buf = new byte[1024];
      int len = is.read(buf);
      System.out.println("客戶端發(fā)送過來的數(shù)據(jù):" + new String(buf, 0, len, StandardCharsets.UTF_8));
      // 給客戶端響應HTTP協(xié)議的數(shù)據(jù)
      OutputStream os = client.getOutputStream();
      os.write(response.getBytes(StandardCharsets.UTF_8));
      // 注意:要關閉客戶端資源
      client.close();
    }
  }
}

只要響應數(shù)據(jù)滿足HTTP協(xié)議,就可以通過瀏覽器訪問到頁面,下面我們使用瀏覽器訪問下

基于NIO的非阻塞簡單服務器實現(xiàn)

傳統(tǒng)BIO會阻塞,使用NIO通道編程可以設置服務器為非阻塞,當未獲取到連接時,可以處理其他的邏輯。相當于線程模型換了。下面是服務端代碼,客戶端代碼不變,采用BIO的即可

public class NioServerSocket {
  public static void main(String[] args) throws IOException, InterruptedException {
    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    serverSocketChannel.bind(new InetSocketAddress("127.0.0.1", 5002));
    serverSocketChannel.configureBlocking(false); // 設置非阻塞
    while (true) {
      SocketChannel clientChannel = serverSocketChannel.accept();
      if (clientChannel == null) {
        System.out.println("客戶端無連接,休息一下");
        Thread.sleep(1000);
        continue;
      }
      Socket socket = clientChannel.socket();
      InputStream is = socket.getInputStream();
      byte[] buf = new byte[1024];
      int len = is.read(buf);
      System.out.println("客戶端發(fā)送過來的數(shù)據(jù):" + new String(buf, 0, len, StandardCharsets.UTF_8));
      socket.close();
      clientChannel.close();
    }
  }
}

第二種實現(xiàn)方式如下

public class NioServerSocket2 {
  public static void main(String[] args) throws IOException, InterruptedException {
    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    serverSocketChannel.bind(new InetSocketAddress("127.0.0.1", 5002));
    serverSocketChannel.configureBlocking(false); // 設置非阻塞
    while (true) {
      SocketChannel clientChannel = serverSocketChannel.accept();
      if (clientChannel == null) {
        System.out.println("客戶端無連接,休息一下");
        Thread.sleep(1000);
        continue;
      }
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      int len = clientChannel.read(buffer);
      System.out.println("客戶端說" + new String(buffer.array(), 0, len));
      clientChannel.close();
    }
  }
}

但是該實現(xiàn)也有一個問題:雖然客戶端的連接過程不會阻塞了,但是客戶端發(fā)送數(shù)據(jù)會阻塞服務端。如果客戶端發(fā)送數(shù)據(jù)過大,假設要10秒,那服務端調(diào)用read方法讀取數(shù)據(jù)就要等待客戶端至少10秒。

基于NIO的Selector的簡單服務器實現(xiàn)

selector的服務端如下,這是要給單線程的服務端。相比上一小節(jié)沒有使用selector,它的優(yōu)點就是連接事件和讀事件都不會阻塞了。即使客戶端發(fā)送數(shù)據(jù)很慢,服務端也不會阻塞。

缺點是單線程執(zhí)行,如果一個線程搶到讀就緒事件并且處理的很慢,就會影響整體性能。

public class NioSelectorServerSocket {
  public static void main(String[] args) throws Exception {
    // 1. 獲取通道
    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    serverSocketChannel.bind(new InetSocketAddress("127.0.0.1", 5003));
    serverSocketChannel.configureBlocking(false);
    // 2. 獲取選擇器
    Selector selector = Selector.open();
    // 3. 把通道注冊到選擇器上,只注冊連接繼續(xù)事件
    serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
    System.out.println("服務器啟動成功...");
    while (true) {
      // 4. 不斷輪詢選擇器中是否由連接事件
      int select = selector.select(2000);
      if (select == 0) {
        System.out.println("暫時沒有客戶端連接哦");
        continue;
      }
      // 5. 如果有連接繼續(xù)事件,獲取客戶端通道
      Set<SelectionKey> selectionKeys = selector.selectedKeys();
      Iterator<SelectionKey> iterator = selectionKeys.iterator();
      while (iterator.hasNext()) {
        SelectionKey key = iterator.next();
        if (key.isAcceptable()) {
          SocketChannel client = serverSocketChannel.accept();
          //SocketChannel client = ((ServerSocketChannel) key.channel()).accept(); // 兩種寫法都一樣
          client.configureBlocking(false);
          // 6. 為每個連接都注冊寫事件監(jiān)聽
          client.register(selector, SelectionKey.OP_READ);
          System.out.println("已注冊可讀事件");
        }
        if (key.isReadable()) {
          SocketChannel client = (SocketChannel) key.channel();
          // 7. 監(jiān)聽到可讀事件,處理可讀事件
          ByteBuffer buffer = ByteBuffer.allocate(1024);
          int len = client.read(buffer);
          System.out.println("客戶端說:" + (len > 0 ? new String(buffer.array(), 0, len, StandardCharsets.UTF_8) : ""));
          // 8. 關閉資源
          client.close();
        }
        iterator.remove();
      }
    }
  }
}

它的線程模型還是用燒水的例子來舉例

總結

到此這篇關于Socket編程簡單示例的文章就介紹到這了,更多相關Socket編程示例內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Scala隱式轉換和隱式參數(shù)詳解

    Scala隱式轉換和隱式參數(shù)詳解

    Scala隱式轉換和隱式參數(shù)是兩個非常強大的功能,它們可以讓我們編寫更靈活和優(yōu)雅的代碼,但也需要注意一些潛在的問題和風險,這篇文章主要介紹了Scala隱式轉換和隱式參數(shù),需要的朋友可以參考下
    2023-04-04
  • SpringCloud Eureka搭建的方法步驟

    SpringCloud Eureka搭建的方法步驟

    這篇文章主要介紹了SpringCloud Eureka搭建的方法步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-01-01
  • slf4j?jcl?jul?log4j1?log4j2?logback各組件系統(tǒng)日志切換

    slf4j?jcl?jul?log4j1?log4j2?logback各組件系統(tǒng)日志切換

    這篇文章主要介紹了slf4j、jcl、jul、log4j1、log4j2、logback的大總結,各個組件的jar包以及目前系統(tǒng)日志需要切換實現(xiàn)方式的方法,有需要的朋友可以借鑒參考下
    2022-03-03
  • 概述java虛擬機中類的加載器及類加載過程

    概述java虛擬機中類的加載器及類加載過程

    這篇文章主要介紹了概述java虛擬機中類的加載器及類加載過程,文中有非常詳細的代碼示例,對正在學習java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • 將本地jar包安裝進入maven倉庫(實現(xiàn)方法)

    將本地jar包安裝進入maven倉庫(實現(xiàn)方法)

    下面小編就為大家?guī)硪黄獙⒈镜豭ar包安裝進入maven倉庫(實現(xiàn)方法)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • 淺談Java中Lambda表達式的相關操作

    淺談Java中Lambda表達式的相關操作

    java8新特性,Lambda是一個匿名函數(shù),類似Python中的Lambda表達式、js中的箭頭函數(shù),目的簡化操作,文中有非常詳細的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • SpringBoot實現(xiàn)異步事件Event詳解

    SpringBoot實現(xiàn)異步事件Event詳解

    這篇文章主要介紹了SpringBoot實現(xiàn)異步事件Event詳解,異步事件的模式,通常將一些非主要的業(yè)務放在監(jiān)聽器中執(zhí)行,因為監(jiān)聽器中存在失敗的風險,所以使用的時候需要注意,需要的朋友可以參考下
    2023-11-11
  • Java中打亂一個數(shù)組的2種公平算法分享

    Java中打亂一個數(shù)組的2種公平算法分享

    這篇文章主要介紹了Java中打亂一個數(shù)組的2種公平算法分享,本文講解了洗牌程序原理、生成隨機索引交換二種方法并給出示例代碼,需要的朋友可以參考下
    2015-03-03
  • SpringBoot工程中Spring Security應用實踐記錄流程分析

    SpringBoot工程中Spring Security應用實踐記錄流程分析

    Spring Security是一個能夠為基于Spring的企業(yè)應用系統(tǒng)提供聲明式的安全訪問控制解決方案的安全框架。這篇文章主要介紹了SpringBoot工程中Spring Security應用實踐,需要的朋友可以參考下
    2021-09-09
  • 關于Java的Condition接口最佳理解方式

    關于Java的Condition接口最佳理解方式

    這篇文章主要介紹了關于Java的Condition接口最佳理解方式,Condition就是實現(xiàn)了管程里面的條件變量,Java?語言內(nèi)置的管程里只有一個條件變量,而Lock&Condition實現(xiàn)的管程支持多個條件變量,需要的朋友可以參考下
    2023-05-05

最新評論

黎城县| 甘南县| 芒康县| 临桂县| 清苑县| 祥云县| 高邑县| 平乡县| 临江市| 襄樊市| 鄂托克旗| 赣州市| 萍乡市| 德惠市| 织金县| 蓬安县| 巨野县| 宜春市| 石狮市| 姚安县| 汝南县| 承德县| 温州市| 珠海市| 柏乡县| 青阳县| 黄梅县| 田东县| 汽车| 抚松县| 深水埗区| 张北县| 宁乡县| 苏尼特左旗| 仁怀市| 都兰县| 万盛区| 泸定县| 新巴尔虎右旗| 朔州市| 汝阳县|