• IO/NIO交互模拟及渐进式实现


    IO

    IO Server

    1. public class SocketServer {
    2. public static void main(String[] args) {
    3. //server编号和client编号对应,优缺点注释在server端
    4. //server1();
    5. //server2();
    6. server3();
    7. }
    8. /**
    9. * server1的缺点:
    10. * 1、accept()方法阻塞了线程,要等客户端连接后才能继续处理(一个客户端连接,对应一个服务端处理线程)
    11. * 2、当客户端与服务端完成一次交互后,程序就结束了
    12. * 3、流关闭代码比较臃肿、BufferedWriter的内容需要在末尾加'\n'
    13. * 4、交互的内容写死,不可以通过控制台输入
    14. * 5、端口号固定、ip固定、readLine读取一行等等
    15. */
    16. public static void server1() {
    17. ServerSocket serverSocket = null;
    18. BufferedReader bufferedReader = null;
    19. BufferedWriter bufferedWriter = null;
    20. try {
    21. serverSocket = new ServerSocket(8999);
    22. //阻塞至客户端连接成功
    23. Socket socket = serverSocket.accept();
    24. bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    25. //readLine会阻塞
    26. String s = bufferedReader.readLine();
    27. System.out.println("服务端接收到客户端的消息:" + s);
    28. bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
    29. bufferedWriter.write("服务端发送消息给客户端\n");
    30. bufferedWriter.flush();
    31. } catch (IOException e) {
    32. throw new RuntimeException(e);
    33. } finally {
    34. //各个try catch 必须分开写,聚合成一个会导致一个流关闭异常,无法进入其他流的关闭流程
    35. if(serverSocket != null) {
    36. try {
    37. serverSocket.close();
    38. } catch (IOException e) {
    39. throw new RuntimeException(e);
    40. }
    41. }
    42. if(bufferedWriter != null) {
    43. try {
    44. bufferedWriter.close();
    45. } catch (IOException e) {
    46. throw new RuntimeException(e);
    47. }
    48. }
    49. //只需要关闭外层的缓冲区,其close方法内部关闭了了传入的流
    50. //如果不关闭,只是等待jvm兜底finally,会在不确定的时间内对资源造成占用(如果是文件读写会对文件描述符fd的占用)
    51. if (bufferedReader != null) {
    52. try {
    53. bufferedReader.close();
    54. } catch (IOException e) {
    55. throw new RuntimeException(e);
    56. }
    57. }
    58. }
    59. }
    60. /**
    61. * server2优点:
    62. * 1、服务端和客户端可以任意次交互,可以连续发送消息
    63. * 2、优化了流关闭的写法
    64. *
    65. * server2的缺点:
    66. * 1、accept()方法阻塞了线程,要等客户端连接后才能继续处理(一个客户端连接,对应一个服务端处理线程)
    67. * 2、cpu空转
    68. * 3、ip固定等等
    69. * 4、一个服务端只能和一个客户端交互
    70. */
    71. public static void server2() {
    72. System.out.println("请输入端口号,并等待客户端连接...");
    73. try (BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
    74. ServerSocket serverSocket = new ServerSocket(Integer.valueOf(consoleReader.readLine()));
    75. Socket socket = serverSocket.accept();
    76. BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    77. PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
    78. ){
    79. System.out.println("客户端已连接,开始和客户端交互...");
    80. //这个循环保证可以连续发送或者接收多条消息
    81. while (true) {
    82. if (bufferedReader.ready()) {
    83. System.out.println("收到客户端的消息:" + bufferedReader.readLine());
    84. }
    85. if (consoleReader.ready()) {
    86. printWriter.println(consoleReader.readLine());
    87. printWriter.flush();
    88. }
    89. }
    90. //只能发一次接收一次
    91. // while (true) {
    92. // System.out.println("收到客户端的消息:" + bufferedReader.readLine());
    93. //
    94. // printWriter.println(consoleReader.readLine());
    95. // printWriter.flush();
    96. // }
    97. } catch (IOException e) {
    98. throw new RuntimeException(e);
    99. }
    100. }
    101. /**
    102. * server3优点:
    103. * 一个服务端可以和一个客户端交互
    104. * 加上了线程池
    105. *
    106. * server3的缺点:
    107. * 1、accept()方法阻塞了线程,要等客户端连接后才能继续处理(一个客户端连接,对应一个服务端处理线程)
    108. * 2、cpu空转
    109. * 3、ip固定等等
    110. * 4、如果开启多个客户端,因System.in被服务端共享,所以服务端发送消息后,客户端会随机接收其中个别消息
    111. */
    112. public static void server3() {
    113. ThreadPoolExecutor pool = new ThreadPoolExecutor(0, Runtime.getRuntime().availableProcessors() * 2,
    114. 60L, TimeUnit.SECONDS,
    115. new SynchronousQueue());
    116. System.out.println("请输入端口号,并等待客户端连接...");
    117. try (BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
    118. ServerSocket serverSocket = new ServerSocket(Integer.valueOf(consoleReader.readLine()));
    119. ){
    120. //这个循环保证多个客户端连接
    121. while (true) {
    122. Thread.sleep(1000);
    123. Socket socket = serverSocket.accept();
    124. System.out.println("客户端已连接,开始和客户端交互...");
    125. pool.submit(new Thread(()->{
    126. try(
    127. BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    128. PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
    129. ) {
    130. while (true) {
    131. Thread.sleep(1000);
    132. if(bufferedReader.ready()) {
    133. System.out.println("收到客户端"+ Thread.currentThread() +"的消息:" + bufferedReader.readLine());
    134. }
    135. if (consoleReader.ready()) {
    136. printWriter.println(consoleReader.readLine());
    137. printWriter.flush();
    138. }
    139. }
    140. } catch (IOException e) {
    141. throw new RuntimeException(e);
    142. } catch (InterruptedException e) {
    143. throw new RuntimeException(e);
    144. } finally {
    145. if(socket != null) {
    146. try {
    147. socket.close();
    148. } catch (IOException e) {
    149. throw new RuntimeException(e);
    150. }
    151. }
    152. }
    153. }));
    154. }
    155. } catch (IOException e) {
    156. throw new RuntimeException(e);
    157. } catch (InterruptedException e) {
    158. throw new RuntimeException(e);
    159. }
    160. }
    161. }

    IO Client

    1. public class SocketClient {
    2. public static void main(String[] args) {
    3. //client1();
    4. //client2();
    5. client3();
    6. }
    7. public static void client1() {
    8. Socket socket = null;
    9. BufferedReader bufferedReader = null;
    10. BufferedWriter bufferedWriter = null;
    11. try {
    12. socket = new Socket("127.0.0.1", 8999);
    13. bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
    14. //换行符必不可少,不然服务端readLine()无法判断一行已经写完
    15. bufferedWriter.write("客户端发送消息给服务端\n");
    16. bufferedWriter.flush();
    17. bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    18. String s = bufferedReader.readLine();
    19. System.out.println("客户端接收到服务端的消息:" + s);
    20. } catch (IOException e) {
    21. throw new RuntimeException(e);
    22. } finally {
    23. if(socket != null) {
    24. try {
    25. socket.close();
    26. } catch (IOException e) {
    27. throw new RuntimeException(e);
    28. }
    29. }
    30. if(bufferedWriter != null) {
    31. try {
    32. bufferedWriter.close();
    33. } catch (IOException e) {
    34. throw new RuntimeException(e);
    35. }
    36. }
    37. if (bufferedReader != null) {
    38. try {
    39. bufferedReader.close();
    40. } catch (IOException e) {
    41. throw new RuntimeException(e);
    42. }
    43. }
    44. }
    45. }
    46. public static void client2() {
    47. System.out.println("请输入端口号:");
    48. try (
    49. BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
    50. Socket socket = new Socket("127.0.0.1", Integer.valueOf(consoleReader.readLine()));
    51. PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
    52. BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    53. ){
    54. System.out.println("连接成功,开始和服务端交互");
    55. //可以连续发送或者接收多条消息
    56. while (true) {
    57. Thread.sleep(1000);
    58. if (bufferedReader.ready()) {
    59. System.out.println("收到服务端的消息:" + bufferedReader.readLine());
    60. }
    61. if (consoleReader.ready()) {
    62. printWriter.println(consoleReader.readLine());
    63. printWriter.flush();
    64. }
    65. }
    66. //只能发一次接收一次
    67. // while (true) {
    68. // printWriter.println(consoleReader.readLine());
    69. // printWriter.flush();
    70. //
    71. // System.out.println("收到服务端的消息:" + bufferedReader.readLine());
    72. // }
    73. } catch (IOException e) {
    74. throw new RuntimeException(e);
    75. } catch (InterruptedException e) {
    76. throw new RuntimeException(e);
    77. }
    78. }
    79. public static void client3() {
    80. System.out.println("请输入端口号:");
    81. try (
    82. BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
    83. Socket socket = new Socket("127.0.0.1", Integer.valueOf(consoleReader.readLine()));
    84. PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
    85. BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    86. ){
    87. System.out.println("连接成功,开始和服务端交互");
    88. //可以连续发送或者接收多条消息
    89. while (true) {
    90. if (bufferedReader.ready()) {
    91. System.out.println("收到服务端的消息:" + bufferedReader.readLine());
    92. }
    93. if (consoleReader.ready()) {
    94. printWriter.println(consoleReader.readLine());
    95. printWriter.flush();
    96. }
    97. }
    98. } catch (IOException e) {
    99. throw new RuntimeException(e);
    100. }
    101. }
    102. }

    NIO

    NIO Server

    1. public class SocketServer {
    2. public static void main(String[] args) {
    3. //server1();
    4. //server2();
    5. //server3();
    6. //server4();
    7. server5();
    8. }
    9. /**
    10. * 优点:NIO非阻塞方式,连接不会阻塞、读写不会阻塞
    11. * 缺点:
    12. * 1、当客户端与服务端完成一次交互后,程序就结束了
    13. * 2、交互的内容写死,不可以通过控制台输入
    14. * 3、cpu空转
    15. * 4、未使用selector多路复用器,其编程其实还是类似与BIO形式(服务端还是每个线程对应一个客户端)
    16. */
    17. private static void server1() {
    18. try (
    19. ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    20. ){
    21. serverSocketChannel.socket().bind(new InetSocketAddress(9999));
    22. serverSocketChannel.configureBlocking(false);
    23. //accept设置了非阻塞,因此需要放置在循环中使用,否则程序直接结束了
    24. while (true) {
    25. Thread.sleep(1000);
    26. SocketChannel socketChannel = serverSocketChannel.accept();
    27. if(socketChannel != null) {
    28. System.out.println("客户端已连接,开始和客户端交互...");
    29. socketChannel.configureBlocking(false);
    30. ByteBuffer readBuffer = ByteBuffer.allocate(1024);
    31. socketChannel.read(readBuffer);
    32. readBuffer.clear();
    33. System.out.println("接收到客户端消息: " + new String(readBuffer.array(), "utf-8").trim());
    34. ByteBuffer writeBuffer = ByteBuffer.wrap("发送消息给客户端".getBytes());
    35. socketChannel.write(writeBuffer);
    36. }
    37. }
    38. } catch (IOException e) {
    39. throw new RuntimeException(e);
    40. } catch (InterruptedException e) {
    41. throw new RuntimeException(e);
    42. }
    43. }
    44. /**
    45. * 改良:
    46. * 1、支持客户端和服务端一对一交互,多发
    47. * 缺点:
    48. * 1、不支持一个客户端对多个服务端
    49. * 2、如果开启多个客户端,因System.in被服务端共享,所以服务端发送消息后,客户端会随机接收其中个别消息
    50. * 3、cpu空转
    51. * 4、未使用selector多路复用器,其编程其实还是类似与BIO形式(服务端还是每个线程对应一个客户端)
    52. */
    53. private static void server2() {
    54. try (
    55. ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    56. BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
    57. ){
    58. serverSocketChannel.socket().bind(new InetSocketAddress(9999));
    59. serverSocketChannel.configureBlocking(false);
    60. //accept设置了非阻塞,因此需要放置在循环中使用,否则程序直接结束了
    61. while (true) {
    62. Thread.sleep(1000);
    63. SocketChannel socketChannel = serverSocketChannel.accept();
    64. if(socketChannel != null) {
    65. System.out.println("客户端已连接,开始和客户端交互...");
    66. socketChannel.configureBlocking(false);
    67. ByteBuffer readBuffer = ByteBuffer.allocate(1024);
    68. while (true) {
    69. if(socketChannel.read(readBuffer) > 0) {
    70. System.out.println("接收到客户端消息: " + new String(readBuffer.array(), "utf-8").trim());
    71. readBuffer.clear();
    72. }
    73. if (consoleReader.ready()) {
    74. ByteBuffer writeBuffer = ByteBuffer.wrap(consoleReader.readLine().getBytes());
    75. socketChannel.write(writeBuffer);
    76. writeBuffer.clear();
    77. }
    78. Thread.sleep(1000);
    79. }
    80. }
    81. }
    82. } catch (IOException e) {
    83. throw new RuntimeException(e);
    84. } catch (InterruptedException e) {
    85. throw new RuntimeException(e);
    86. }
    87. }
    88. /**
    89. * 改良:
    90. * 1、支持一个客户端对多个服务端
    91. * 缺点:
    92. * 1、cpu空转
    93. * 2、未使用selector多路复用器,其编程其实还是类似与BIO形式(服务端还是每个线程对应一个客户端)
    94. */
    95. private static void server3() {
    96. try (
    97. ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    98. BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
    99. ) {
    100. serverSocketChannel.socket().bind(new InetSocketAddress(9999));
    101. serverSocketChannel.configureBlocking(false);
    102. List socketChannels = new ArrayList<>();
    103. //accept设置了非阻塞,因此需要放置在循环中使用,否则程序直接结束了
    104. while (true) {
    105. Thread.sleep(1000);
    106. boolean ready = consoleReader.ready();
    107. byte[] bytes = null;
    108. if (ready) {
    109. bytes = consoleReader.readLine().getBytes();
    110. }
    111. //调用一次accept再次使用会变成成null,除非有新的客户端连接
    112. SocketChannel socketChannel = serverSocketChannel.accept();
    113. if (socketChannel != null) {
    114. socketChannels.add(socketChannel);
    115. socketChannel.configureBlocking(false);
    116. System.out.println("客户端已连接,开始和客户端交互...");
    117. }
    118. for (SocketChannel channel : socketChannels) {
    119. ByteBuffer readBuffer = ByteBuffer.allocate(1024);
    120. if (channel.read(readBuffer) > 0) {
    121. System.out.println("接收到客户端消息: " + new String(readBuffer.array(), "utf-8").trim());
    122. readBuffer.clear();
    123. }
    124. if (ready) {
    125. ByteBuffer writeBuffer = ByteBuffer.wrap(bytes);
    126. channel.write(writeBuffer);
    127. writeBuffer.clear();
    128. }
    129. }
    130. }
    131. } catch (IOException e) {
    132. throw new RuntimeException(e);
    133. } catch (InterruptedException e) {
    134. throw new RuntimeException(e);
    135. }
    136. }
    137. /**
    138. * 改良:
    139. * 1、支持一个客户端对多个服务端 (服务端发送消息,客户端都能收到,所有客户端发送消息服务端都能收到)
    140. * 2、相对与server3多线程方式,服务端只需要启动一个主线程即可与所有客户端交互,
    141. * 缺点:
    142. * 1、cpu空转
    143. * 2、未使用selector多路复用器,其编程其实还是类似与BIO形式(服务端还是每个线程对应一个客户端)
    144. */
    145. static final List socketChannels4 = new CopyOnWriteArrayList<>();
    146. private static void server4() {
    147. try (
    148. ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    149. BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
    150. ) {
    151. serverSocketChannel.socket().bind(new InetSocketAddress(9999));
    152. serverSocketChannel.configureBlocking(false);
    153. //accept设置了非阻塞,因此需要放置在循环中使用,否则程序直接结束了
    154. while (true) {
    155. SocketChannel socketChannel = serverSocketChannel.accept();
    156. if (socketChannel != null) {
    157. System.out.println("客户端已连接,开始和客户端交互...");
    158. socketChannel.configureBlocking(false);
    159. socketChannels4.add(socketChannel);
    160. }
    161. Iterator iterator = socketChannels4.iterator();
    162. boolean ready = consoleReader.ready();
    163. byte[] writeBytes = null;
    164. if (ready) {
    165. writeBytes = consoleReader.readLine().getBytes();
    166. }
    167. while (iterator.hasNext()) {
    168. ByteBuffer readBuffer = ByteBuffer.allocate(1024);
    169. SocketChannel channel = iterator.next();
    170. if (channel.read(readBuffer) > 0) {
    171. System.out.println("接收到客户端消息: " + new String(readBuffer.array(), "utf-8").trim());
    172. readBuffer.clear();
    173. }
    174. if (ready) {
    175. ByteBuffer writeBuffer = ByteBuffer.wrap(writeBytes);
    176. channel.write(writeBuffer);
    177. writeBuffer.clear();
    178. }
    179. }
    180. Thread.sleep(1000);
    181. }
    182. } catch (IOException | InterruptedException e) {
    183. throw new RuntimeException(e);
    184. }
    185. }
    186. /**
    187. * 改良:
    188. * 1、支持一个客户端对多个服务端 (服务端发送消息,客户端都能收到,所有客户端发送消息服务端都能收到)
    189. * 2、相对与server3多线程方式,服务端只需要启动一个主线程即可与所有客户端交互,
    190. * 缺点:
    191. * 1、cpu空转
    192. * 2、未使用selector多路复用器,其编程其实还是类似与BIO形式(服务端还是每个线程对应一个客户端)
    193. */
    194. private static void server5() {
    195. try (ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    196. Selector selector = Selector.open();
    197. BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
    198. ) {
    199. serverSocketChannel.socket().bind(new InetSocketAddress(9999));
    200. serverSocketChannel.configureBlocking(false);
    201. //将serverSocketChannel注册到selector, 并监听accept事件
    202. serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
    203. List socketChannels = new ArrayList<>();
    204. while (true) {
    205. //非阻塞
    206. selector.select(1000);
    207. Iterator iterator = selector.selectedKeys().iterator();
    208. while (iterator.hasNext()) {
    209. SelectionKey selectionKey = iterator.next();
    210. if(selectionKey.isAcceptable()) {
    211. SocketChannel socketChannel = serverSocketChannel.accept();
    212. System.out.println("客户端已连接,开始和客户端交互...");
    213. socketChannel.configureBlocking(false);
    214. socketChannel.register(selector, SelectionKey.OP_READ);
    215. socketChannels.add(socketChannel);
    216. } else if(selectionKey.isReadable()) {
    217. SocketChannel socketChannel = (SocketChannel)selectionKey.channel();
    218. ByteBuffer readBuffer = ByteBuffer.allocate(1024);
    219. if (socketChannel.read(readBuffer) > 0) {
    220. System.out.println("接收到客户端消息: " + new String(readBuffer.array(), "utf-8").trim());
    221. readBuffer.clear();
    222. }
    223. }
    224. iterator.remove();
    225. }
    226. if(consoleReader.ready()) {
    227. byte[] bytes = consoleReader.readLine().getBytes();
    228. for (SocketChannel socketChannel : socketChannels) {
    229. ByteBuffer writeBuffer = ByteBuffer.wrap(bytes);
    230. socketChannel.write(writeBuffer);
    231. writeBuffer.clear();
    232. }
    233. }
    234. }
    235. } catch (IOException e) {
    236. throw new RuntimeException(e);
    237. }
    238. }
    239. }

    NIO Client

    1. public class SocketClient {
    2. public static void main(String[] args) {
    3. //client1();
    4. //client2_3_4();
    5. client5();
    6. }
    7. private static void client1() {
    8. try (
    9. SocketChannel socketChannel = SocketChannel.open();
    10. ){
    11. socketChannel.configureBlocking(false);
    12. socketChannel.connect(new InetSocketAddress("127.0.0.1", 9999));
    13. while (!socketChannel.finishConnect()) {
    14. Thread.sleep(1000);
    15. System.out.println("正在连接客户端...");
    16. }
    17. ByteBuffer writeBuffer = ByteBuffer.wrap("向服务端发送消息".getBytes());
    18. socketChannel.write(writeBuffer);
    19. writeBuffer.clear();
    20. ByteBuffer readBuffer = ByteBuffer.allocate(1024);
    21. while (true) {
    22. if(socketChannel.read(readBuffer) > 0) {
    23. System.out.println("接收到服务端消息: " + new String(readBuffer.array(), "utf-8").trim());
    24. readBuffer.clear();
    25. break;
    26. }
    27. Thread.sleep(1000);
    28. }
    29. } catch (IOException | InterruptedException e) {
    30. throw new RuntimeException(e);
    31. }
    32. }
    33. private static void client2_3_4() {
    34. try (
    35. SocketChannel socketChannel = SocketChannel.open();
    36. BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
    37. ){
    38. socketChannel.configureBlocking(false);
    39. socketChannel.connect(new InetSocketAddress("127.0.0.1", 9999));
    40. while (!socketChannel.finishConnect()) {
    41. Thread.sleep(1000);
    42. System.out.println("正在连接客户端...");
    43. }
    44. ByteBuffer readBuffer = ByteBuffer.allocate(1024);
    45. while (true) {
    46. if(socketChannel.read(readBuffer) > 0) {
    47. System.out.println("接收到服务端消息: " + new String(readBuffer.array(), "utf-8").trim());
    48. readBuffer.clear();
    49. }
    50. if (consoleReader.ready()) {
    51. ByteBuffer writeBuffer = ByteBuffer.wrap(consoleReader.readLine().getBytes());
    52. socketChannel.write(writeBuffer);
    53. writeBuffer.clear();
    54. }
    55. Thread.sleep(1000);
    56. }
    57. } catch (IOException | InterruptedException e) {
    58. throw new RuntimeException(e);
    59. }
    60. }
    61. private static void client5() {
    62. try (
    63. SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9999));
    64. Selector selector = Selector.open();
    65. BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
    66. ){
    67. socketChannel.configureBlocking(false);
    68. socketChannel.register(selector, SelectionKey.OP_READ);
    69. while (true) {
    70. selector.select(1000);
    71. Iterator iterator = selector.selectedKeys().iterator();
    72. while (iterator.hasNext()) {
    73. SelectionKey selectionKey = iterator.next();
    74. if (selectionKey.isReadable()) {
    75. SocketChannel channel = (SocketChannel) selectionKey.channel();
    76. ByteBuffer readBuffer = ByteBuffer.allocate(1024);
    77. if(channel.read(readBuffer) > 0) {
    78. System.out.println("接收到服务端消息: " + new String(readBuffer.array(), "utf-8").trim());
    79. readBuffer.clear();
    80. }
    81. }
    82. iterator.remove();
    83. }
    84. if (consoleReader.ready()){
    85. ByteBuffer writeBuffer = ByteBuffer.wrap(consoleReader.readLine().getBytes());
    86. socketChannel.write(writeBuffer);
    87. writeBuffer.clear();
    88. }
    89. }
    90. } catch (IOException e) {
    91. throw new RuntimeException(e);
    92. }
    93. }
    94. }

  • 相关阅读:
    Unity --- UI图像,锚点与轴心点
    神经网络(第二周)
    SpringBoot读取Yml中基本数据类型、List、Map、数组数据
    MUSIQ: Multi-scale Image Quality Transformer【图像质量评估】
    抽奖小游戏
    树形DP 复习笔记
    免费开源的100套Echarts大屏数据可视化模板分享
    观察者模式
    Python字典
    使用Vagrant创建和管理本地Kubernetes(K8s)集群的步骤是什么
  • 原文地址:https://blog.csdn.net/z275598733/article/details/133921600