java结合NIO实现的聊天程序
2014-02-20 11:30
288 查看
ChatClient:
import java.net.*; import java.nio.*; import java.nio.channels.*; import java.nio.charset.*; import java.awt.*; import java.awt.event.*; public class ChatClient { private SocketChannel sc = null; private String name = null; private Frame f; private TextArea ta; private TextField tf; private boolean runnable = true; public static void main(String[] args){ ChatClient cc = new ChatClient(); cc.createUI(); cc.inputName(); cc.connect(); new ReceiveThread(cc,cc.getTextArea()).start(); } public SocketChannel getSc(){ return sc; } public void setName(String name){ this.name = name; } public TextArea getTextArea(){ return ta; } public TextField getTextField(){ return tf; } public boolean getRunnable(){ return runnable; } public void stop(){ runnable = false; } public void shutDown(){ try{ sc.write(ByteBuffer.wrap("bye".getBytes("UTF-8"))); ta.append("Exit in 5 seconds!"); this.stop(); Thread.sleep(5000); sc.close(); }catch(Exception e){ e.printStackTrace(); } System.exit(0); } public void createUI(){ f = new Frame("Client"); ta = new TextArea(); ta.setEditable(false); tf = new TextField(); Button send = new Button("Send"); Panel p = new Panel(); p.setLayout(new BorderLayout()); p.add(tf,"Center"); p.add(send,"East"); f.add(ta,"Center"); f.add(p,"South"); MyClientListener listener = new MyClientListener(this); send.addActionListener(listener); tf.addActionListener(listener); f.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){ ChatClient.this.shutDown(); } }); f.setSize(400,400); f.setLocation(600,0); f.setVisible(true); tf.requestFocus(); } public boolean connect()(){ try{ sc = SocketChannel.open(); //"czd"为目标计算机名 InetSocketAddress isa = new InetSocketAddress("172.16.32.63",8814); sc.connect(isa); sc.configureBlocking(false); sc.write(ByteBuffer.wrap(name.getBytes("UTF-8"))); }catch(Exception e){ e.printStackTrace(); } return true; } public void inputName(){ String name = javax.swing.JOptionPane.showInputDialog("Input Your Name:"); this.setName(name); f.setTitle(name); } } class MyClientListener implements ActionListener{ private ChatClient client; public MyClientListener(ChatClient client){ this.client = client; } public void actionPerformed(ActionEvent e){ TextField tf = client.getTextField(); String info = tf.getText(); if(info.equals("bye")){ client.shutDown(); }else{ try{ client.getSc().write(ByteBuffer.wrap(info.getBytes("UTF-8"))); }catch (Exception e1) { e1.printStackTrace(); } } tf.setText(""); tf.requestFocus(); } } class ReceiveThread extends Thread{ private ChatClient client; private TextArea ta; public ReceiveThread(ChatClient client,TextArea ta){ this.client = client; this.ta = ta; } public void run(){ SocketChannel sc = client.getSc(); ByteBuffer byteBuffer = ByteBuffer.allocate(2048); CharBuffer charBuffer = null; Charset charset = Charset.forName("UTF-8"); CharsetDecoder decoder = charset.newDecoder(); String msg = null; int n = 0; try{ while(client.getRunnable()){ n = sc.read(byteBuffer); if(n>0){ byteBuffer.flip(); charBuffer = decoder.decode(byteBuffer); msg = charBuffer.toString(); ta.append(msg + "\n"); } byteBuffer.clear(); Thread.sleep(500); } }catch(Exception e){ e.printStackTrace(); System.exit(0); } } }ICQServer:
import java.io.*; import java.nio.*; import java.nio.channels.*; import java.nio.charset.*; import java.net.*; import java.util.*; public class ICQServer { private Selector select()or = null; private ServerSocketChannel ssc = null; //服务器端通信端口号 private int port = 8814; //在线用户列表 private Hashtable<String, SocketChannel> userList = null; public ICQServer() {} public ICQServer(int port) { this.port = port; } //初始化服务器 public void init() { try { //创建选择器对象 selector = Selector.open(); //创建ServerSocketChannel ssc = ServerSocketChannel.open(); //设置ServerSocketChannel为非阻塞模式 ssc.configureBlocking(false); InetAddress ip = InetAddress.getLocalHost(); System.out.println("主机地址 --------> " + ip); InetSocketAddress isa = new InetSocketAddress(ip, port); //将与本通道相关的服务器套接字对象绑定到指定地址和端口 ssc.socket()().bind(isa); //创建在线用户列表 userList = new Hashtable<String, SocketChannel> (); } catch (IOException e) { System.out.println("初始化服务器时异常,原因 --------> " + e.getMessage()); } } //启动服务器 public void start() { try { //将ServerSocketChannel注册到Selector上,准备接收新连接请求 SelectionKey acceptKey = ssc.register(selector, SelectionKey.OP_ACCEPT); SocketChannel sc; int n; String name; //用户名 String msg; //用户发言信息 while (true) { //选择当前所有处于就绪状态的通道所对应的选择键,并将这些键组成已选择键集 n = selector.select(); //n为已选择键集中键的个数 if (n > 0) { //获取此选择器的已选择键集。 Set readyKeys = selector.selectedKeys(); Iterator it = readyKeys.iterator(); //遍历当前已选择键集 while (it.hasNext()) { SelectionKey key = (SelectionKey) it.next(); //从当前已选择键集中移除当前键,避免重复处理 it.remove(); //如果当前键对应的通道已准备好接受新的套接字连接 if (key.isAcceptable()) { //获取当前键对应的可选择通道(ServerSocketChannel) ssc = (ServerSocketChannel) key.channel(); //接收新的套接字连接请求,返回新建的SocketChannel sc = (SocketChannel) ssc.accept(); //如果有新用户接入 if (sc != null) { //接收新上线用户姓名 name = readMessage(sc); //设置新建的SocketChannel为非阻塞模式 sc.configureBlocking(false); //将新建的SocketChannel注册到Selector上,准备进行数据"写"操作, //并将当前用户名以附件的方式附带记录到新建的选择键上。 SelectionKey newKey = sc.register(selector,SelectionKey.OP_WRITE, name); //将新上线用户信息加入到在线用户列表 userList.put(name, sc); //发送"新用户上线"通知 transmitMessage(name + " in!", "--Server Info--"); } //否则,如果当前键对应的通道已准备好进行"写"操作 }else if (key.isWritable()) { //获取当前键对应的可选择通道(SocketChannel) sc = (SocketChannel) key.channel(); //接收该通道相应用户的发言信息 msg = readMessage(sc); //获取选择键上附带记录的当前用户名 name = key.attachment().toString(); //如果用户提出要下线 if (msg.equals("bye")) { //从在线用户列表中移除当前用户 userList.remove(name); //注销当前选择键对应的注册关系 key.cancel(); //关闭当前可选择通道 sc.close(); //发送"用户下线"通知 transmitMessage(name + " out!", "--Server Info--"); //否则,如果接收到的用户发言信息非空("") } else if (msg.length() > 0) { //转发用户发言信息 transmitMessage(msg, name); } } } } //延时循环,降低服务器端处理负荷 Thread.sleep(500); } }catch (Exception e) { System.out.println("启动服务器时异常,原因 --------> " + e.getMessage()); } } //转发用户发言信息 public void transmitMessage(String msg, String name) { try { ByteBuffer buffer = ByteBuffer.wrap( (name + ":" + msg).getBytes("UTF-8")); //将字节数组包装到缓冲区中 Collection channels = userList.values(); SocketChannel sc; for (Object o : channels) { sc = (SocketChannel) o; sc.write(buffer); //将缓冲区数据写入聊天面板(TextArea) buffer.flip(); //将缓冲区ByteBuffer的极限值设置为当前数据实际大小,将缓冲区的值设置为0 } }catch (Exception e) { System.out.println("转发用户发言信息时异常,原因 --------> " + e.getMessage()); } } //接收用户发言信息 public String readMessage(SocketChannel sc) { String result = null; int n = 0; ByteBuffer buf = ByteBuffer.allocate(1024); try { n = sc.read(buf); buf.flip(); Charset charset = Charset.forName("UTF-8"); CharsetDecoder decoder = charset.newDecoder(); CharBuffer charBuffer = decoder.decode(buf); result = charBuffer.toString(); }catch (IOException e) { System.out.println("接收用户发言信息时异常,原因 --------> " + e.getMessage()); } return result; } public static void main(String args[]) { ICQServer server = new ICQServer(); server.init(); server.start(); } }
相关文章推荐
- java用ServerSocket类结合io流实现一对一聊天(java实现简单的TCP聊天程序只能用telnet连接后方可使用)
- java实现基于Tcp的socket聊天程序
- java学习笔记: 实现简易局域网聊天程序
- Java实现多个客户端聊天程序
- Java实现多个客户端聊天程序
- java实现简单聊天程序(集合,线程,I/O,网络编程)
- 黑马程序员-JAVA学习之用多线程实现简单UDP聊天程序
- Java实现多个客户端聊天程序
- Java_GUI创建单机版QQ聊天小程序并实现简单的小功能(附所有源码)
- java实现简单聊天程序(集合,线程,I/O,网络编程)
- java实现简单聊天程序(集合,线程,I/O,网络编程)
- java网络socket编程(七)之java中NIO实现聊天系统的群聊功能
- Java聊天程序的实现
- java实现的聊天程序
- java-用java.net.Socket和java.net.ServerSocket实现简单的聊天程序
- JAVA实现UDP组播聊天程序
- 一个Java实现的简单的多个客户端聊天程序(未测试)
- java实现简单TCP聊天程序
- java swing实现简单的socket通讯聊天程序源码
- java控制台实现QQ聊天程序