Java编写一个简单的“服务器—客户端”聊天程序

鄙人以MyEclipse为平台实现简单的聊天程序
1、创建一个Server类模块:创建ServerSocket,在指定端口监听;当有用户登录, 接受套接字输入流,显示其登录信息,调用ServerHander线程进行管理。
代码实现:

public class Server {
	private ServerSocket server;
	public Server(int port) throws IOException{ 
		server = new ServerSocket(port);  // new一个实例对象端口
		
		while(true){    
		   Socket conn=server.accept(); //建立客户端套接字 
		   DataInputStream in =new DataInputStream(conn.getInputStream()); 
		   String who=in.readUTF();
		   System.out.print("Client" +"(ip:"+conn.getInetAddress()+")"+who+" 进入!"+"\n"); 
		   ServerHander cn=new ServerHander(who,conn);
		   cn.start(); 
     }
}
public static void main(String []args)throws IOException{ 
          new Server(9595);
	}  
}//Server类模块结束

2、创建ServerHander模块:这个模块是整个服务器实现与客户端交互的核心代码,互相添加或者解密关键字,实现群聊、私聊上下线提醒的功能,创建Vector 对象,可以方便用户管理,Vector对象是可变数组,可以实现线程同步。用户发送消息通过关键字@进行解析 ,@前面的字符串为发送的消息,后面的字符串为发送对象。
2.1创建线程

 Socket socket;
		 DataInputStream in;
		 DataOutputStream out;
		 String who;
protected static Vectoruser=new Vector();//把用户线程放入可变对象数组
public ServerHander(String name,Socket socket) throws IOException{   
	this.who = name;
	this.socket = socket;
	in =new DataInputStream(new BufferedInputStream(socket.getInputStream()));
	out =new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
}
public void run(){
	try{ 
		user.addElement(this); //Vector中增加新线程
		sendallclient(who+"上线");
		senduser();//为每一个客户端更新在线用户
while(true){ 
		String news=in.readUTF();
		int index = news.lastIndexOf("@");//对客户 端发过来的信息做相应的处理
		String str = news.substring(index+1,news.length());//取得发送对象和发送的消息
		news=news.substring(0,index);
		
if(str.equals("所有人")==false){
		  sendallclient(who+"对"+str+"说:"+news+"@"); //不是发给所有人则增添标记@
		   }
else                  
		sendallclient(who+"对所有人说: "+news);
		}
}
		catch(IOException e){ 
		     System.out.println("error");
}
		finally{
			user.removeElement(this);
			System.out.print("Client" +"(ip:"+socket.getInetAddress()+")"+who+" 退出!欢迎下次登录"+"\n");
			sendallclient(who+"下线");
		try{
		   socket.close();
	}
		catch(IOException e){  
		     System.out.println("closing");
			}
		}
	}

2.2、创建send all client类模块: 把news消息发送给每一个用户。其中AllClients是 ServerHander的枚举类型,可以指向每一个用户。

protected static void sendallclient(String news){
		    synchronized (user){
		     Enumeration  AllClients=user.elements();
			while(AllClients.hasMoreElements()){
			 ServerHander serh=(ServerHander)AllClients.nextElement();
		try{
		    serh.out.writeUTF(news);
			serh.out.flush();
			}catch(IOException e){
			serh.interrupt();
	    }
	 }
   }
}  //Send all client类模块结束

2.3、创建Send user类模块:更新用户列表 ;实现方法是在名字信息后面加上“$”关键字,达到实现新用户获得除自己外的所有用户名单,而以前的所有用户都在聊天名单中加入这个新用户。

public static synchronized void senduser(){
	for(int j=0;j

3、创建Client类:实现每个客户登录操作

public class Client {
  public ServiceFrame sf;
  private Socket csocket;
  private DataInputStream in;
  private DataOutputStream out;
  public static void main(String []args){
     BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
	 System.out.println("请输入登录用户名: ");
	 String who=" ";
	 try{
	    who=in.readLine().trim();//控制台获得名字
	    } 
   catch(IOException e){
    e.printStackTrace();
	}
	new Client(who,"127.0.0.1",9595);
	}
   public Client(String who,String server,int port){
   sf=new ServiceFrame(who+" 的客户端");
   String str1 = null;
   sf.but.addActionListener(new ActListener(this,sf));
   sf.addWindowListener(new ExitListener(this));
   try{       csocket =new Socket(server,port);
   in=new DataInputStream(new BufferedInputStream(csocket.getInputStream()));
   out=new DataOutputStream(new  BufferedOutputStream(csocket.getOutputStream()));
   out.writeUTF(who);
   out.flush();//名字发给服务器
   while(true){
   str1 = in.readUTF();//重点!!!,服务器端发来的消息
      if(str1.endsWith("$"))//若以$结尾,则增添用户
	  {int index = str1.lastIndexOf("$");
	  String str2 = str1.substring(0,index);
	  sf.friendlist.addItem(str2.trim());
	  }
	 else if(str1.endsWith("@"))//以@结尾为私聊信息
	 {str1=str1.substring(0,str1.length()-1);
	if(str1.contains(who))
	sf.showAT.append("-- "+str1+"\n");
	}else{
	 if(str1.endsWith("下线"))//用户下线,删除此用户
{ int index = str1.lastIndexOf("下线");
String str2 = str1.substring(0,index);
sf.friendlist.removeItem(str2.trim());}
sf.showAT.append("-- "+str1+"\n");
  }sf.showCount.setText("在线人 数:"+(sf.friendlist.getItemCount()-1));  //动态更新在线人数
  }
}catch(Exception e){
   System.out.println("Server Error");
   this.close();       System.exit(0);
     }
}
  protected void send(String msg){//发送消息给服务器的方法
   try{
   out.writeUTF(msg);
   out.flush();
   }catch(Exception e){  }
   }
   protected void close(){
  try{
  sf.dispose();
  out.close();
  in.close();
  csocket.close();
     }catch(IOException ex){}
   }
   }

4、创建服务器的ServiceFrame类

class ServiceFrame extends Frame{
	private static final long serialVersionUID = 1L;
JTextArea showAT;
 JTextField sendFD;
 JComboBox friendlist;
 JButton but;
 JLabel showCount;
 JScrollPane textAreaScrollPane;
 JPanel textFieldPanel = new JPanel();
 @SuppressWarnings("deprecation")
public ServiceFrame (String winname){
      super(winname);//继承父类的名字
	  setSize(500,400);
	  textFieldPanel.setLayout(new FlowLayout(0,10,10));
	  showAT = new JTextArea(400,400);
	  showAT.setEditable(false);
	  textAreaScrollPane = new JScrollPane(showAT);
	  add(textAreaScrollPane, BorderLayout.CENTER);
	  add(textFieldPanel, BorderLayout.SOUTH);
	  friendlist = new JComboBox();
	  friendlist.addItem("所有人");
	  textFieldPanel.add(friendlist);
	  sendFD = new JTextField(20);
	  textFieldPanel.add(sendFD);
	  but = new JButton("发送");
	  but.setMnemonic(KeyEvent.VK_ENTER);
	  textFieldPanel.add(but);
	showCount = new JLabel("在线人数:1");
textFieldPanel.add(showCount); 
     show();
  }
}

5、设置客户端信息发送监听器 ActListener。

class ActListener implements ActionListener {
    Client client;
	ServiceFrame sframe;
	public ActListener(Client c,ServiceFrame sf){
	client=c;    sframe=sf;
}
   public void actionPerformed(ActionEvent e){//发送信息,并以@作为私聊标记
  client.send(sframe.sendFD.getText().trim()+"@"+sframe.friendlist.getSelectedItem());
  sframe.sendFD.setText(" ");
   }
 }

6、设置客户端用户退出监听器 ExitListener。

class ExitListener extends WindowAdapter{
   Client client;
   public ExitListener(Client c){
   client=c;
   }
  public void windowClosing(WindowEvent e){
 client.close();
System.exit(0);
   }
  }

服务器运行结果:
Java编写一个简单的“服务器—客户端”聊天程序_第1张图片

客户端用户登录:
Java编写一个简单的“服务器—客户端”聊天程序_第2张图片

登录成功:
Java编写一个简单的“服务器—客户端”聊天程序_第3张图片

Java编写一个简单的“服务器—客户端”聊天程序_第4张图片

开始聊天:

Java编写一个简单的“服务器—客户端”聊天程序_第5张图片

单对单聊天:
Java编写一个简单的“服务器—客户端”聊天程序_第6张图片

下线通知:
Java编写一个简单的“服务器—客户端”聊天程序_第7张图片

你可能感兴趣的:(Java列传,Java,聊天程序,客户端,服务器)