实现多客户聊天

实际应用中,应该是客户端与客户端聊天,而不是客户端与服务器聊天。客户端与客户端聊天的本质是信息由服务器转发。

编写服务器程序:
要使服务器可以接收多个客户的连接,需要注意以下几个问题:
1.由于事先不知道客户端什么时候连过来,因此,服务器必须首先有一个线程负责多个客户端连接。
结构如下:

public class Server extends JFrame implements Runnable{
	public Server(){
		//服务器打开端口
		//服务器开启线程,接收客户端连接
	}

	pubic void run(){
		//不断接收客户端连接
		while(true){
			//接收客户端连接
			//开一个聊天线程给这个客户端
			//将该聊天线程对象添加进集合
			//聊天线程启动
		}
	}

}

2.当客户端连接上之后,服务器端要等待这些客户端传送信息过来,而事先并不知道客户端什么时候会发信息过来。所以,每一个客户端连上之后,必须为这个客户端单独开一个线程,来读取它发过来的信息。因此,需要再编写一个线程类。

3.服务器收到某个客户端信息之后,需要将其转发给各个客户端,这就需要在服务器端保存各个客户端的输入输出流的引用(实际上,这些引用可以保存在为客户端服务的线程中)。

编写客户端程序:
客户端编程相对简单,只需要编写发送信息,连接服务器,接收服务器传输的信息即可。

运行结果:
首先运行服务器端代码
在这里插入图片描述
再运行一次客户端代码:
在这里插入图片描述
输入昵称后点击确定显示连接成功
在这里插入图片描述
这时就有一个客户Lucy连接上服务器了,类似的再运行几次客户端代码使多个客户连接上该服务器得到
在下面的粉色输入框中输入需要进行通信的内容,按下回车,信息将会发送并且每个连接该服务器的客户均能收到消息
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
服务器端代码:

package 多人聊天;

import java.awt.Color;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JTextArea;

public class Server extends JFrame implements Runnable{
	private Socket s = null;
	private ServerSocket ss = null;
	private ArrayList clients = new ArrayList();//保存客户端的线程
	private JTextArea text = new JTextArea();
	
	public Server() throws Exception{
		this.setTitle("服务器端");
		this.setDefaultCloseOperation(3);
		this.setLocationRelativeTo(null);
		this.setBackground(Color.YELLOW);
		this.setSize(300, 400);
		this.add(text);
		this.setVisible(true);
		ss = new ServerSocket(8080);//服务器开辟端口,接收连接
		new Thread(this).start();//接受客户的死循环开始运行
	}
	
	@Override
	public void run() {
		while(true) {
			try {
				s = ss.accept();
				//s即为当前连接对应的Socket,对应一个客户端
				//该客户端随时可能发信息过来,必须要接收
				//另开辟一个线程,专门为这个s服务,负责接受信息
				ChatThread ct = new ChatThread(s);
				clients.add(ct);
				ct.start();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}
	
	class ChatThread extends Thread{//为某个Socket负责接收信息
		private Socket s = null;
		private BufferedReader br = null;
		public PrintStream ps = null;
		
		public ChatThread(Socket s) throws Exception{
			this.s = s;
			br = new BufferedReader(new InputStreamReader(s.getInputStream()));
			ps = new PrintStream(s.getOutputStream());
			
		}
		
		public void run() {
			while(true) {
				try {
					String str = br.readLine();
					sendMessage(str);//将str转发给所有的客户端
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}//读取该Socket传来额ix信息
			}
		}
	}
		
	public void sendMessage(String msg) {//将信息发给所有的客户端
		for(int i = 0;i<clients.size();i++) {
			ChatThread ct = (ChatThread)clients.get(i);
			//向ct内的Socket内写msg
			ct.ps.println(msg);
		}
	}
		
	public static void main(String[] args)throws Exception{
			Server server = new Server();
	}
}

客户端代码:

package 多人聊天;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class Client extends JFrame implements ActionListener,Runnable{
	private JTextArea taMsg = new JTextArea("以下是聊天记录\n");
	private JTextField tfMsg = new JTextField();
	private Socket s = null;
	private String nickName = null;
	
	public Client() {
		this.setTitle("客户端");
		this.setDefaultCloseOperation(3);
		this.setLocationRelativeTo(null);
		this.add(taMsg,BorderLayout.CENTER);
		tfMsg.setBackground(Color.PINK);
		this.add(tfMsg, BorderLayout.SOUTH);
		tfMsg.addActionListener(this);
		this.setSize(650, 500);
		this.setVisible(true);
		
		nickName = JOptionPane.showInputDialog("请输入昵称");
		
		try {
			s = new Socket("192.168.32.1",8080);
			JOptionPane.showMessageDialog(this, "连接成功");
			this.setTitle("客户端:"+nickName);
			new Thread(this).start();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	@Override
	public void run() {
		while(true) {
			InputStream in;
			try {
				in = s.getInputStream();
				BufferedReader br = new BufferedReader(new InputStreamReader(in));
				String str = br.readLine();
				taMsg.append(str+"\n");
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
		try {
			OutputStream os = s.getOutputStream();
			PrintStream ps = new PrintStream(os);
			ps.println(nickName+":"+tfMsg.getText());
			tfMsg.setText("");
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
		
	}
	
	public static void main(String[] args) throws Exception{
		Client client = new Client();
	}
	
}

猜你喜欢

转载自blog.csdn.net/weixin_42882887/article/details/83213812
今日推荐