简单客户端的实现:
可以理解为客户端和服务器端的通信是在Socket对象上进行的,那么客户端要与服务器端连接起来,首先就是要创建一个Socket对象:
Socket client = new Socket(“IP”,port);
通信的步骤就是:
1、 客户端连结服务器,服务器要求客户端输入用户名及密码。
2、 客户端输入用户名和密码,服务器验证用户信息是否正确。若信息不相符,则提示用户信息有错。
3、 若通过验证,服务器则给其他在线客户机发送消息:该用户上线,目前在线人数几人。
4、 在线用户通过输入框向服务器发送消息,服务器会转发给其他所有的在线用户。
5、 当某个客户端退出,服务器通知其他客户机:某用户下线,当前在线人数几人。
简化来说,基本的通信过程应该是:
1、 客户端从输入框读取消息,发送信息给服务器端,服务器端的输入流读入。
2、 然后服务器端的输出流写出,客户端的输入流读入,并显示在客户端的输出界面上。
所以客户端的连接对象创建后,也需要得到输入输出流,以及读取消息、发送消息的方法。与服务器端相同,客户端中的连接处理的类也是一个线程类,因为从服务器 消息的方法存在阻塞,需要使用到线程。另外,客户端还需要一个界面类,有发送消息的输入框和显示聊天消息的文本框。
NetClient类:包含通信的基本方法,是一个线程类,发送输入框的消息,并聊天内容到文本框。
public class NetClient extends Thread{ private String ip; private int port; private javax.swing.JTextArea jta; private BufferedReader brd; private OutputStream ous; private Socket client; //构造器,创建对象时要有指定的IP及端口还有输出框 public NetClient(String ip,int port,javax.swing.JTextArea jta){ this.ip = ip; this.port = port; this.jta = jta; } /** * 连结服务器是否成功的方法 * @return */ public boolean conn2Server(){ try{//创建一个到服务器端的socket对象 client = new Socket(ip,port); //得到输入流输出流对象 InputStream ins = client.getInputStream(); brd = new BufferedReader(new InputStreamReader(ins)); ous = client.getOutputStream(); return true; }catch(Exception ef){ ef.printStackTrace(); } return false; } /** * 发送消息到服务器的方法 */ public void sendMsg(String msg){ try{ msg+="\r\n"; ous.write(msg.getBytes()); ous.flush(); }catch(Exception ef){ ef.printStackTrace(); } } /** * 从服务器读取消息的方法,有阻塞,需要使用线程 * @return * @throws IOException */ public String readMsg() throws IOException{ String input = brd.readLine(); //将此消息显示到界面 jta.append(input+"\r\n"); return input; } public void run(){ try{ String s = this.readMsg(); while(!"bye".equals(s)){ s = this.readMsg(); } client.close(); }catch(Exception ef){ ef.printStackTrace(); } } }
ClientUI类:显示客户端界面。并启动客户端线程的方法。
public class ClientUI extends JFrame{ private javax.swing.JTextArea jta_output = new javax.swing.JTextArea(12,25); private NetClient nc; public static void main(String[] args) { ClientUI cu = new ClientUI(); cu.setUpThread(); } /** * 启动客户端连结线程方法 */ public void setUpThread(){ nc = new NetClient("localhost",9090,jta_output); if(nc.conn2Server()){ this.showUI(); nc.start(); } } /** * 显示界面的方法 */ public void showUI(){ this.setTitle("客户端聊天窗口"); this.setSize(300,400); this.setLayout(new java.awt.FlowLayout()); this.add(jta_output); final javax.swing.JTextArea jta_input = new javax.swing.JTextArea(5,25); this.add(jta_input); javax.swing.JButton bu_send = new javax.swing.JButton("Send"); this.add(bu_send); ActionListener al = new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { String msg = jta_input.getText(); nc.sendMsg(msg); jta_input.setText(""); } }; bu_send.addActionListener(al); //jta_input.addAncestorListener(al); this.setVisible(true); } }
运行后聊天过程如下: