NIOChatClient.java 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package cn.hhj.nio.chat;
  2. import java.io.IOException;
  3. import java.net.InetSocketAddress;
  4. import java.nio.ByteBuffer;
  5. import java.nio.channels.SelectionKey;
  6. import java.nio.channels.Selector;
  7. import java.nio.channels.SocketChannel;
  8. import java.nio.charset.Charset;
  9. import java.util.Iterator;
  10. import java.util.Scanner;
  11. import java.util.Set;
  12. public class NIOChatClient {
  13. private final InetSocketAddress serverAdrress = new InetSocketAddress("localhost", 8080);
  14. private Selector selector = null;
  15. private SocketChannel client = null;
  16. private String nickName = "";
  17. private Charset charset = Charset.forName("UTF-8");
  18. private static String USER_EXIST = "系统提示:该昵称已经存在,请换一个昵称";
  19. private static String USER_CONTENT_SPILIT = "#@#";
  20. public NIOChatClient() throws IOException{
  21. selector = Selector.open();
  22. //连接远程主机的IP和端口
  23. client = SocketChannel.open(serverAdrress);
  24. client.configureBlocking(false);
  25. client.register(selector, SelectionKey.OP_READ);
  26. }
  27. public void session(){
  28. //开辟一个新线程从服务器端读数据
  29. new Reader().start();
  30. //开辟一个新线程往服务器端写数据
  31. new Writer().start();
  32. }
  33. private class Writer extends Thread{
  34. @Override
  35. public void run() {
  36. try{
  37. //在主线程中 从键盘读取数据输入到服务器端
  38. Scanner scan = new Scanner(System.in);
  39. while(scan.hasNextLine()){
  40. String line = scan.nextLine();
  41. if("".equals(line)) continue; //不允许发空消息
  42. if("".equals(nickName)) {
  43. nickName = line;
  44. line = nickName + USER_CONTENT_SPILIT;
  45. } else {
  46. line = nickName + USER_CONTENT_SPILIT + line;
  47. }
  48. // client.register(selector, SelectionKey.OP_WRITE);
  49. client.write(charset.encode(line));//client既能写也能读,这边是写
  50. }
  51. scan.close();
  52. }catch(Exception e){
  53. }
  54. }
  55. }
  56. private class Reader extends Thread {
  57. public void run() {
  58. try {
  59. while(true) {
  60. int readyChannels = selector.select();
  61. if(readyChannels == 0) continue;
  62. Set<SelectionKey> selectedKeys = selector.selectedKeys(); //可以通过这个方法,知道可用通道的集合
  63. Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
  64. while(keyIterator.hasNext()) {
  65. SelectionKey key = (SelectionKey) keyIterator.next();
  66. keyIterator.remove();
  67. process(key);
  68. }
  69. }
  70. }
  71. catch (IOException io){
  72. }
  73. }
  74. private void process(SelectionKey key) throws IOException {
  75. if(key.isReadable()){
  76. //使用 NIOServerDemoBak 读取 Channel中的数据,这个和全局变量client是一样的,因为只注册了一个SocketChannel
  77. //client既能写也能读,这边是读
  78. SocketChannel sc = (SocketChannel)key.channel();
  79. ByteBuffer buff = ByteBuffer.allocate(1024);
  80. String content = "";
  81. while(sc.read(buff) > 0)
  82. {
  83. buff.flip();
  84. content += charset.decode(buff);
  85. }
  86. //若系统发送通知名字已经存在,则需要换个昵称
  87. if(USER_EXIST.equals(content)) {
  88. nickName = "";
  89. }
  90. System.out.println(content);
  91. key.interestOps(SelectionKey.OP_READ);
  92. }
  93. }
  94. }
  95. public static void main(String[] args) throws IOException {
  96. new NIOChatClient().session();
  97. }
  98. }