当前位置:文档之家› java 简单聊天室程序

java 简单聊天室程序

简单聊天室程序先运行Server,然后运行test。

有简单的界面登录成功后实现群聊,-to name something 实现单独聊天package chatroom;import java.io.IOException;import .DatagramPacket;import .DatagramSocket;import .InetAddress;import .SocketAddress;import .SocketException;import .UnknownHostException;import java.util.Enumeration;import java.util.Hashtable;import java.util.Scanner;public class Server implements Runnable{private DatagramSocket server = null;private DatagramPacket getDatas = null;private InetAddress serverAddress = null;private int port = 0;//开始运行监听的变量private boolean beStart = false;//用来测试服务器的变量private boolean test = true;//信息存储器private Hashtable<String,SocketAddress> infoMemory = new Hashtable<String,SocketAddress>();/*** 测试服务器连接* @param ip* @param port* @return*/public boolean testServer(String ip,int port) {this.initServer(ip, port);return test;}/*** 服务器初始化* @param ip* @param port*/public void initServer(String ip,int port) {//确定IP与port输入正确this.fixServerLink(ip,port);try {server = new DatagramSocket(this.port,serverAddress);System.out.println("!-The Server Initialization Success!");//可以开始运行变量beStart = true;} catch (SocketException s) {//如果出现异常,则服务器测试不通过test = false;errorTip("!-The Server Initialization Fail!");}}/*** 确定服务器IP和端口信息* @param ip* @param port*/private void fixServerLink(String ip,int port) {//判断连接服务器的端口号//如果输入命令为0,则为默认端口号9999//否则端口号为新端口号if(port == 0)this.port = 9999;elsethis.port = port;//判断连接服务器的IP地址//如果输入命令为0,则为默认的本地IP地址//否则为输入的IP地址try {if(ip.equalsIgnoreCase("0"))this.serverAddress = InetAddress.getLocalHost();elsethis.serverAddress = InetAddress.getByName(ip);} catch (UnknownHostException u) {errorTip("!-Sorry, IP address you put is not currect!");}}* 监听信息**/public void listenLink() {byte[] buf = new byte[1024];String mes = null;try {getDatas = new DatagramPacket(buf,buf.length);System.out.println("!-The Server starts listenning to message.");while(beStart) {server.receive(getDatas);mes = new String(buf,0,getDatas.getLength());//将获取的数据传递至数据分析器this.analyseMes(mes);}} catch (IOException e) {errorTip("!-The Server Can not receive message");}}/*** 数据分析器,给予相应处理* @param mes*/private void analyseMes(String mes) {//获取当前客户端的地址:SocketAddress adr = getDatas.getSocketAddress();//-test:进行服务器与客户端的连接测试//若成功,则将该客户端发送成功消息if(mes.trim().equalsIgnoreCase("-test")) {transforMesSingle(adr,"-test: !-From Server:Succeed in Testing.");}//-quit:接受客户端退出信息//将该用户的退出信息转发至所有在线成员else if(mes.trim().equalsIgnoreCase("-quit")) {String name = this.getConsumerName(adr);System.out.println(name+"//"+adr+" quit! ");transforMes("* "+name+"退出聊天室");infoMemory.remove(name);}//-getList:接受客户端获取列表的请求//将所有用户连接为字符串的形式,如:"-getList,用户1,用户2...用户n"else if(mes.trim().equals("-getList")) {StringBuffer list = new StringBuffer();list.append("-getList,");Enumeration<String> names = infoMemory.keys();while (names.hasMoreElements()) {list.append(names.nextElement()+",");}transforMesSingle(getDatas.getSocketAddress(),list.toString());}//-to:接受客户端请求,将信息转发给相应客户//如果目标客户不存在,则向请求客户发送相应消息else if(mes.indexOf("-to ") != -1 && mes.startsWith("-to ")) {String main = mes.substring("-to ".length(),mes.length());String toName = main.substring(0,main.indexOf(" "));String name = this.getConsumerName(adr);String con = name+" say to you :"+main.substring(toName.length()+1,main.length());if(!infoMemory.containsKey(toName))transforMesSingle(adr,"!-The message can not be recevie by whom you send for,please check out.");elsetransforMesSingle(infoMemory.get(toName),con);}//-nick:接受客户端登录请求//如果输入的匿名不存在,则登记该用户与infoMemory//如果存在则返回相应提示else if(mes.indexOf("-nick ") != -1 && mes.startsWith("-nick ")) {String nickName = mes.substring("-nick ".length(), mes.length());infoMemory.put(nickName,adr);transforMes("欢迎"+nickName +" 来到聊天室!");System.out.println(nickName+"//"+adr.toString()+"连接成功");}//一般消息将会转发至所有用户else {String name = this.getConsumerName(adr);transforMes(name+": "+mes);}}/*** 通过地址得到用户的昵称* 由于Hashtable无法通过Value获取Key,所有专门写该方法* @param sa* @return*/private String getConsumerName(SocketAddress sa) {Enumeration<String> names = infoMemory.keys();String name = null;while (names.hasMoreElements()) {String temp = names.nextElement();SocketAddress adrs = infoMemory.get(temp);//进行比较if (sa.equals(adrs)) {name = temp;break;}}return name;}/*** 向所有的用户发送数据* @param mes*/public void transforMes(String mes) {byte[] buf = mes.getBytes();DatagramPacket sendDatas = null;Enumeration<SocketAddress> all = infoMemory.elements();try {while (all.hasMoreElements()) {sendDatas = new DatagramPacket(buf,buf.length,all.nextElement());server.send(sendDatas);}} catch (SocketException s) {errorTip("!-The feedback address is error!");} catch (IOException i) {errorTip("!-Can not send message!");}}/*** 向单个用户发送数据* @param adr* @param mes*/public void transforMesSingle(SocketAddress adr,String mes) {byte[] buf = mes.getBytes();try {DatagramPacket sendDatas = new DatagramPacket(buf,buf.length,adr);server.send(sendDatas);} catch (SocketException s) {errorTip("!-The feedback address is error!");} catch (IOException i) {errorTip("!-Can not send message!");}}/*** 断开连接**/public void cutServer() {beStart = false;if(server != null)server.close();System.out.println("!-The server is done.");}public void helpList() {System.out.println("-help"+"获取服务器相应操作的帮助"+"n"+"-run "+"运行服务器,并同时建立信息监听"+"n"+"-stop"+"停止服务器"+"n"+"-quit"+"停止服务器,并退出命令"+"n");}/*** 线程*/public void run() {listenLink();}/*** 主要操作* @param args*/public static void main(String[] args) {Server ser = new Server();String getIp = null;int getPort = 0;Scanner input = new Scanner(System.in);//建立输入boolean goon = true;while (goon){System.out.println("1.输入服务器的IP地址,默认输入数字0:");getIp = input.next();System.out.println("2.输入服务器的端口号,默认输入数字0:");try {getPort = input.nextInt();} catch (Exception e) {System.out.println("!-The port style is not currect!");}//测试服务器创建,如果成功则同时为信息监听器建立线程System.out.println("!-创建服务器并运行...");if (ser.testServer(getIp, getPort)) {new Thread(ser).start();goon = false;} elseSystem.out.println("!-服务器创建失败,请检查!");}}/*** 错误提示* @param str*/public static void errorTip(String str) {System.out.println("-----------------n"+str+"n-----------------");}}package chatroom;import java.awt.GridLayout;import java.awt.ScrollPane;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.*;import .*;import java.util.InputMismatchException;import java.util.NoSuchElementException;import java.util.Scanner;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JPanel;import javax.swing.JPasswordField;import javax.swing.JTextArea;import javax.swing.JTextField;public class Consumer implements Runnable{//发送数据的服务器Net地址,在fixServerLink //和sendMes方法中会用到private InetAddress sendAddress = null;private int port = 0;//客户端private DatagramSocket client = null;//发送的数据报private DatagramPacket sendDatas = null;//用来测试是否能够连接成功或者用户名是否正确//在testConnect和checkNickName中会用到.//并穿插在sendMes方法中private boolean test = true;static final JTextArea jt10 = new JTextArea();static final JTextArea jt3 = new JTextArea();Scanner s = new Scanner(System.in);private String u_Id;private String u_Name;private String u_Password;private int index = 0;int k =0;public String getU_Id() {return u_Id;}public void setU_Id(String u_Id) {this.u_Id = u_Id;}public String getU_Name() {return u_Name;}public void setU_Name(String u_Name) {this.u_Name = u_Name;}public String getU_Password() {return u_Password;}public void setU_Password(String u_Password) {this.u_Password = u_Password;}static Consumer users[] = new Consumer[100];public void UserWriter(){OutputStream os = null;File file = new File("F://User.txt");try {os = new FileOutputStream(file);} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}String str="";for(int i=0;i<users.length;i++){if(users[i]!=null){String temp = str + users[i].getU_Id() + "," + users[i].getU_Name()+ ","+ users[i].getU_Password()+";";str = temp;}}try {os.write(str.getBytes());} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public void UserReader(){//初始化时从文件中读取数据File file = new File("F://User.txt");if(!file.exists()){try {file.createNewFile();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if(file.length()==0){users = null;users = new Consumer[100];}else{InputStream is = null;try {is = new FileInputStream(file);} catch (FileNotFoundException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}byte byt[] = new byte[(int)file.length()];try {is.read(byt);String temp = new String(byt);String user1[] = temp.split(";");for(int i =0;i<user1.length;i++){String date[] =user1[i].split(",");String id = date[0];String name = date[1];String password = date[2];Consumer ut = new Consumer();ut.setU_Id(id);ut.setU_Name(name);ut.setU_Password(password);users[i] = ut;}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{try {is.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}public void Registor(){erReader();// 创建窗体JFrame jf = new JFrame("注册");// 创建容器JPanel jp = new JPanel();// 为容器添加布局管理器jp.setLayout(new GridLayout(4,3));// 创建组建JLabel j1 = new JLabel("用户名:");JLabel j2 = new JLabel("用户密码:");JLabel j3 = new JLabel("重复密码:");JLabel j4 = new JLabel();final JLabel j5 = new JLabel();final JLabel j6 = new JLabel();final JLabel j7 = new JLabel();final JTextField name = new JTextField(8);final JPasswordField pwd = new JPasswordField(8);final JPasswordField pwd_ag = new JPasswordField(8);final JButton but = new JButton("注册");JPanel jp1 = new JPanel();jp1.setLayout(new GridLayout(1,3));jp1.add(j5);jp1.add(but);// 将组件添加到容器jp.add(j1);jp.add(name);jp.add(j5);jp.add(j2);jp.add(pwd);jp.add(j6);jp.add(j3);jp.add(pwd_ag);jp.add(j7);jp.add(j4);jp.add(jp1);// 将容器添加到窗体jf.add(jp);// 设置窗体大小jf.setSize(300,150);// 设置初始位置jf.setLocation(300,200);// 设置可见jf.setVisible(true);// 设置窗体是否可调jf.setResizable(false);// 添加监听器but.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {System.out.println("监听器开始工作");String u_name = name.getText();String u_pwd = new String(pwd.getPassword());String u_pwd_ag =new String( pwd_ag.getPassword());int index = 0;Consumer u0 = new Consumer();//判断用户名是否在普通用户中已存在if(u_name.length()!=0){for(int i =0;i < users.length;i++){if(users[i]!=null){if(u_name.equals(users[i].getU_Id())){j5.setText("用户名已存在");break;}}else{index =1;u0.setU_Id(u_name);}}}else{j5.setText("用户名不能为空!");}if(index ==1){if(u_pwd.equals(u_pwd_ag)){if(u_pwd.length()!=0){u0.setU_Password(u_pwd_ag);for(int i=0;i<users.length;i++){if(users[i]==null){if(users[i]==null){users[i]=u0;j5.setText("恭喜你!注册成功!");name.setText(null);pwd.setText(null);pwd_ag.setText(null);break;}}}}else{j6.setText("密码不能为空!");}}else{j6.setText("两次输入密码不一致,请重新注册!");}}}});erWriter();}public void Login(){erReader();// 创建窗体和容器final JFrame jf = new JFrame("登录");JPanel jp = new JPanel();// 创建组件JLabel jl1 = new JLabel("用户名:");JLabel jl2 = new JLabel("用户密码:");JButton but1 = new JButton("注册");JButton but2 = new JButton("登录");final JTextField name = new JTextField(8);final JPasswordField pwd = new JPasswordField(8); // 为容器创建布局管理器jp.setLayout(new GridLayout(3,2));JPanel jp1 = new JPanel();//jp1.setLayout()// 将组件添加到容器jp.add(jl1);jp.add(name);jp.add(jl2);jp.add(pwd);jp.add(but1);jp.add(but2);// 将容器添加到窗体jf.add(jp);// 窗体设置jf.setSize(300,150);jf.setLocation(300,200);jf.setVisible(true);jf.setResizable(false);// 添加监听器but1.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {Registor();}});but2.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {final Consumer consumer = new Consumer();erReader();Scanner s = new Scanner(System.in);String Id = name.getText();for(int i = 0;i<users.length;i++){if(users[i]!=null){if(users[i].getU_Id().equals(Id)){String password = new String(pwd.getPassword());if(password.equals(users[i].getU_Password())){jf.setVisible(false);send(Id);break;}else{new Demo01().WrongPwd();break;}}}else {new Demo01().WrongName();break;}}}});}/**** 建立连接* @param ip服务器IP号* @param port 服务器Port*/public void connectServer(String ip,int port) {//先确定输入的IP与端口号是否符合规则this.fixServerLink(ip,port);//try {try {client = new DatagramSocket();} catch (SocketException e) {// TODO Auto-generated catch blockSystem.out.println("The Connection of server is error.");}//} catch(SocketException s) {//System.out.println("The Connection of server is error.");//}}/*** 确定IP与Port输入是否正确* @param ip* @param port*/private void fixServerLink(String ip,int port) {//判断连接服务器的端口号//如果输入命令为0,则为默认端口号9999//否则端口号为新端口号if(port == 0)this.port = 9999;elsethis.port = port;//判断连接服务器的IP地址//如果输入命令为0,则为默认的本地IP地址//否则为输入的IP地址try {if(ip.equalsIgnoreCase("0"))this.sendAddress = InetAddress.getLocalHost();elsethis.sendAddress = InetAddress.getByName(ip);} catch (UnknownHostException e) {// TODO Auto-generated catch blockSystem.out.println("Sorry, IP address you put is not currect!");}//try {//} catch (UnknownHostException u) {//System.out.println("Sorry, IP address you put is not currect!");//}}/*** 断开连接*/public void disconnectServer() {//当客户端断开连接之前,客户端会向服务器端发送一个信息,//以便告诉服务器该客户下线this.sendMes("-quit");if(client != null){client.close();}}/*** 发送消息* @param mes*/public void sendMes(String mes) {byte[] buf = mes.getBytes();sendDatas = new DatagramPacket(buf,buf.length,sendAddress,port); //当建立发送时,测试正常test = true;try {client.send(sendDatas);} catch (NullPointerException n) {//如果无法得到要发送的消息,测试终止test = false;System.out.println("无法得到要发送的消息");} catch (IOException s) {//如果无法发送消息至服务器,测试终止test = false;System.out.println("无法发送到服务器");}}/*** 得到数据*/public void getMes() {String str = null;byte[] buf = new byte[1024];DatagramPacket getDatas = new DatagramPacket(buf,buf.length);String mes = null;try {while(true) {client.receive(getDatas);mes = new String(buf,0,getDatas.getLength());//如果服务器发送的消息中的头片段有-getList//表明客户端获得在线用户列表,调用getList方法解析if(mes.indexOf("-getList") == 0)this.getList(mes);else{jt10.append(mes+"\n");System.out.println(mes);}}} catch (IOException i) {System.out.println("Fail in receving message");}}/*** 得到一次数据**/public String getMesOnce() {byte[] buf = new byte[1024];DatagramPacket getDatas = new DatagramPacket(buf,buf.length);String mes = null;try {client.receive(getDatas);mes = new String(buf,0,getDatas.getLength());} catch (Exception e) {System.out.println("!-Can not receive the message!");} finally {}return mes;}/*** 显示在线用户列表* @param mes*/private void getList(String mes) {String[] list = mes.split(",");jt3.setText("");for(int i = 1;i<list.length;i++) {jt3.append("----"+list[i]+"---"+"\n");}}/*** 测试连接* @param ip* @param port* @return*/public boolean testConnect(String ip,int port) {//创建连接,测试连接是否正确this.connectServer(ip,port);//如果连接正确,试图发送测试标识"-test"//在发送数据过程中测试连接是否正确this.sendMes("-test");//如果连接发送测试通过//则开始测试是否能够正确if (test) {String mes = this.getMesOnce();//如果服务器返回相应的标识,测试通过if (mes.startsWith("-test")) {test = true;}}if(client != null) {client.close();}return test;}/*** 判断用户名输入是否正确*/// private boolean checkNickName(String nickName) {// test = true;// String mes = null;////判断昵称是否符合约定// for(int i = 0;i<nickName.length();i++) {// char temp = nickName.charAt(i);////如果不符合,则终止测试// if(!Character.isLetterOrDigit(temp)) {// test = false;// break;// }// }////如果通过约定,则试图向服务器发送昵称,进行判断// if (test) {// this.sendMes("-nick "+nickName);// mes = this.getMesOnce();////如果服务器返回"-nick"标识////说明测试昵称失败,终止测试// if (mes.startsWith("-nick")) {// test = false;// }// }//// System.out.println(mes);// return test;// }/*** 得到帮助列表**/public void helpList() {System.out.println("重要说明:如果已经成功连接,只要输入内容,所有在线用户都能看到您的发言。

相关主题