利用java网络通信技术实现一个迷你QQ

利用Java网络通信技术实现一个迷你聊天室

说明:此聊天室由四个类构成,ChatRoomServer.java,是聊天室的服务器,要是一直开启状态,然后是客户端方面的LinkServerFrame.java,Client.java和ClientFrame.java。
可以打开多个客户端,只要连接在同一个局域网就可以互相聊天啦!下面是代码和运行截图:

1.首先是服务器类 ChatRoomServer.java

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashSet;

public class ChatRoomServer {
	private HashSet<Socket> allSockets;//客户端套接字集合
	private ServerSocket serverSocket;//服务器套接字
	
	public  ChatRoomServer(){
		try {
			serverSocket = new ServerSocket(4545);
		} catch (IOException e) {
			e.printStackTrace();
		}
		allSockets = new HashSet<Socket>();
	}
	
	public void startServer() throws IOException{
		while(true){
			Socket socket = serverSocket.accept();//获得一个客户端连接
			System.out.println("用户已经进入聊天室");
			allSockets.add(socket);//将客户端连接的套接字放到集合中
			ServerThread t = new ServerThread(socket);
			t.start();
		}
	}
	
	private class ServerThread extends Thread{
		Socket socket;
		
		public ServerThread(Socket socket) {
            this.socket = socket;
        }    
		public void run() {
			BufferedReader br = null;
			try {
				br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			while(true){
				try {
					String str = br.readLine();
					if(str.contains("EXIT")){//%EXIT:用户名%
						String tmp = str.split(":")[1]+"用户退出聊天室";
						sendMessageToAllClient(tmp);
						allSockets.remove(socket);
						socket.close();
						return;
					}
					sendMessageToAllClient(str);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			
		}
	}
	
	private void sendMessageToAllClient(String str){
		for(Socket s:allSockets){
			try {
				BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
				bw.write(str);
				bw.newLine();
				bw.flush();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args){
		try {
			ChatRoomServer s = new ChatRoomServer();
			s.startServer();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

服务器端大功告成开始搭建客户端!

2.连接服务器的界面类:LinkServerFrame.java

import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.JobAttributes;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.*;

public class LinkServerFrame extends JFrame{//连接服务器的窗体
	public JTextField textFieid1;//接收服务器IP地址的文本框
	public JTextField textFieid2;//接受用户名的文本框
	public JButton button;//连接服务器
	public JLabel label1;//服务器IP地址
	public JLabel label2;//用户名
	
	public LinkServerFrame() {
		textFieid1 = new JTextField();
		textFieid2 = new JTextField();
		button = new JButton("连接服务器");
		label1 = new JLabel("   服 务 器 I P 地 址:");
		label2 = new JLabel("   用 户 名:");
		
		button.addActionListener(new ActionListener() {		
			public void actionPerformed(ActionEvent e) {
				if(!textFieid1.getText().equals("")&&!textFieid2.getText().equals("")){
					//文本框内容不为空
					dispose();//销毁当前窗体
					//创建客户端窗体并传参
					try {
						ClientFrame clientFrame = new ClientFrame(textFieid1.getText().trim(), textFieid2.getText().trim());
						clientFrame.setVisible(true);
					} catch (IOException e1) {
						e1.printStackTrace();
					}
				}else{
					JOptionPane.showMessageDialog(null,"文本框的内容不能为空!","警告",JOptionPane.WARNING_MESSAGE);
				}
			}
		});
		
		JPanel north = new JPanel(new GridLayout(2,2,10,10));
		JPanel south = new JPanel(new FlowLayout());
		
		north.add(label1);
		north.add(textFieid1);
		north.add(label2);
		north.add(textFieid2);
		south.add(button);
		
		setTitle("连接服务器");
		setVisible(true);
		setBounds(200, 200, 400, 200);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		Container c = getContentPane();//获取容器
		c.setLayout(new GridLayout(2,1,10,10));//网格布局,两行一列
		c.add(north);//添加面板
		c.add(south);
	}
	
	public static void main(String[] args) {
		new LinkServerFrame();
	}
}

3.然后是客户端类:Client.java

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class Client {
	private Socket socket;
	private BufferedWriter bw;
	private BufferedReader br;
	
	public Client(String ip,int port) throws IOException{
		socket = new Socket(ip,port);
		bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
		br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
	}
	
	public void sendMessage(String message) throws IOException{
		bw.write(message);
		bw.newLine();
		bw.flush();
	}
	
	public String reciveMessage() throws IOException{
		String message = null;
		message = br.readLine();
		return message;
	}
	
	public void close(){
		try {
			socket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

4.最后客户端界面类ClientFrame .java

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.*;

public class ClientFrame extends JFrame{
	private JPanel contentPane;//中间面板
	private JPanel southPane;//底部面板
	private JLabel lblUserName;//显示用户名
	private JTextField tfMessage;//信息发送文本
	private JButton btnSend;//发送按钮
	private JTextArea textArea;//信息接收文本域
	private String userName;//用户名称
	Client client;//客户端连接对象
	
	private void init(){
		setTitle("聊天室");
		setResizable(true);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(200,200,450,300);
		
		lblUserName = new JLabel(userName);//初始化各个标签
		tfMessage = new JTextField(25);
		btnSend = new JButton("发送");
		textArea = new JTextArea(50,40);
		
		contentPane = new JPanel();//中间面板
		contentPane.add(textArea);
		southPane = new JPanel(new FlowLayout());//底部面板浮动排版
		
		southPane.add(lblUserName,new FlowLayout().LEFT);
		southPane.add(tfMessage);
		southPane.add(btnSend, new FlowLayout().RIGHT);
		
		Container c = getContentPane();//获取容器
		c.add(contentPane,new BorderLayout().CENTER);//将面板添加到容器中
		c.add(southPane,new BorderLayout().SOUTH);
	}
	
	public ClientFrame(String ip,String userNmae) throws IOException {
		this.userName = userNmae;
		init();//添加窗体初始化内容
		addListener();//添加监听事件

		client = new Client(ip,4545);//创建客户端对象
		
		ReadMessageThread t = new ReadMessageThread();
		t.start();
	}
	
	private class ReadMessageThread extends Thread{
		@Override
		public void run() {
			while(true){
				try {
					String str = client.reciveMessage();
					textArea.append(str+"\n");
				} catch (IOException e) {
					e.printStackTrace();
				}
				
			}
		}
	} 
	
	private void addListener() {
		btnSend.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				Date date = new Date();
				SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
				try {
					client.sendMessage(userName+" "+df.format(date)+":\n "+tfMessage.getText());
					tfMessage.setText("");//清空输入框
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		});
		
		this.addWindowListener(new WindowAdapter() {//开启窗口监听事件
			public void windowClosing(WindowEvent e){
				int op = JOptionPane.showConfirmDialog(ClientFrame.this,"确定退出聊天室么?","确定",JOptionPane.YES_NO_OPTION);
				if(op == JOptionPane.YES_OPTION){//如果选择是
					try {
						client.sendMessage("%EXIT%:"+userName);//发送消息
						try {
							Thread.sleep(200);
						} catch (InterruptedException e1) {
							e1.printStackTrace();
						}
					} catch (IOException e1) {
						e1.printStackTrace();
					}
					client.close();//关闭客户端线程
					System.exit(0);		
				}
			}
		});
	}
}

先启动服务器,然后再启动客户端,输入服务器的IP地址就可以啦!这个小程序可以和舍友之间(连接同一个电脑开的wifi就行)聊天,迷你QQ,你值得拥有

发布了34 篇原创文章 · 获赞 65 · 访问量 3744

猜你喜欢

转载自blog.csdn.net/baidu_41860619/article/details/103505570