IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 基于C/S模式的简单聊天室 -> 正文阅读

[网络协议]基于C/S模式的简单聊天室

基于C/S模式的简单聊天室

要求:
使用Socket实现网上聊天室,要求基于TCP或UDP协议,用户可以通过客户端连接到服务器端并进行聊天,聊天时可以启动多个客户端;服务器启动后,接收客户端发来的用户名和验证信息,验证通过则可以加入聊天室,当客户退出聊天时在聊天室公告改用户退出信息;要求界面美观。

  • 流程图

程序运行流程图

  • 运行结果
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

  • 代码重现
    客户端界面
// ClientFrame.java
package client;

import java.awt.*;
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.net.InetAddress;
import java.util.Vector;

import javax.swing.*;

public class ClientFrame extends JFrame {
	JTextField field1; // 信息发送文本框
	
	JTextField usernamefield1; // 用户名文本框
		
	JPasswordField passwordfield2; // 密码文本框
	
	JLabel label1; // 显示用户名
	
	JLabel label2; // 显示密码

	JPanel panel;// 下方面板

	JTextArea area;// 信息接收文本域

	JButton button;// 发送按钮

	String userName;// 用户名称
	
	String passWord;// 用户密码
	
	Vector<String> username = new Vector(6);
	
	Vector<String> password = new Vector(6);
	
	int flag;// 密码验证是否正确的标志,flag=1成功,flag=0失败
	
	boolean is_empty = true;// 密码验证是否为空的标志

	ChatRoomClient client;// 客户端连接对象

	public ClientFrame() {
		setUser();
		do {
			try {
				// 手动输入IP地址进行连接服务器
				//String host = JOptionPane.showInputDialog(this, "请输入服务器IP地址");
				// 自动获取IP地址连接服务器
				String host = InetAddress.getLocalHost().getHostAddress().toString();
				if (host == null) {
					System.exit(0);// 如果host是空的,则关闭程序
				}
				client = new ChatRoomClient(host, 5678);// 连接服务器的5678接口
			} catch (IOException e) {
				e.printStackTrace();
				JOptionPane.showMessageDialog(this, "网络无法连接,请重新设置参数");
			}
		} while (client == null);// 如果客户端没有关闭,则一直连接
		
		
		while(is_empty) {// 验证输入的用户名、密码是否为空
			field1 = new JTextField(25);
			String str = JOptionPane.showInputDialog(this, "请输入用户名:");
			userName = str.trim();		
			usernamefield1 = new JTextField(15);			
			label1 = new JLabel(userName);			
			String str2 = JOptionPane.showInputDialog(this, "请输入"+userName+"的密码:");
			passWord = str2.trim();
			passwordfield2 = new JPasswordField(15);
			passwordfield2.setEchoChar('*');
			label2 = new JLabel(passWord);
			
			// 空:while循环重新输入,否则直接进入客户端client			
			is_empty = is_empty(userName,passWord);		
			
			// 验证用户名、密码是否正确
			int yz = is_true(userName,passWord);
			if(yz == 1) {
				area = new JTextArea(20, 15);
				area.setEditable(false);
				button = new JButton("发送");
				panel = new JPanel();
				
				init();
				addEventHandler();
			}else {
				if(is_empty == false) {
					JOptionPane.showMessageDialog(null, "账号或密码错误,请重新输入", "提示", 1);
				}
				is_empty = true;// 账号或密码错误,将用户名密码置空,is_empty置为true				
				}
			}
		}
	
	// 验证用户名、密码是否为空
	public boolean is_empty(String userName, String passWord) {
		// TODO Auto-generated method stub
		if(userName.length() == 0) {	
			is_empty = true;
			JOptionPane.showMessageDialog(this, "用户名不能为空");
		}else if(passWord.length() == 0){
			is_empty = true;
			JOptionPane.showMessageDialog(this, "密码不能为空");
		}else {
			is_empty = false;
		}
		return is_empty;
	}

	// 设定初始的用户和密码
	void setUser() {
		username.add("张三");
		username.add("李四");
		username.add("王五");
		
		password.add("zs123");
		password.add("ls123");
		password.add("ww123");
		
	}
	
	// 初始化方法
	public void init() {
		//add();
		JScrollPane jsp = new JScrollPane(area);// 添加滚动条
		this.setTitle(" 602聊天室");
		this.add(jsp);
		panel.add(label1);
		//panel.add(label2);
		panel.add(field1);
		//panel.add(passwordfield2);
		panel.add(button);

		this.add(panel, BorderLayout.SOUTH);// 下方面板,布局位置为南
	}
	
	// 展示窗口
	public void showMe() {
		this.pack();// 调整此窗口的大小,以适合其子组件的首选大小和布局。
		this.setVisible(true);// 窗口可显示
		this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);// 点击窗口叉,不做任何操作
		new ReadMessageThread().start();// 开启线程
	}
	
	
	// 验证用户名密码是否一致
	public int is_true(String userName,String passWord) {	
//		System.out.println(username.size());
		flag = 0;
		for(int i=0;i<username.size();i++) {
			if(username.get(i).equals(userName) && password.get(i).equals(passWord)){
				flag = 1;
			}
		}
		if(flag == 1) {
			JOptionPane.showMessageDialog(null, "登录成功", "提示", -1);
		}
//		else {
//			JOptionPane.showMessageDialog(null, "账号或密码错误,请重新输入", "提示", 1);
//			field1.setText("");
//			passwordfield2.setText("");
//			new ClientFrame().showMe();
//		}
		return flag;
	}

	// 添加监听方法
	public void addEventHandler() {
		
		button.addActionListener(new ActionListener() {// 开启按钮监听
			public void actionPerformed(ActionEvent e) {
				// 判断消息是否为空
				if(field1.getText().length() == 0) {
					JOptionPane.showMessageDialog(null, "消息不能为空", "注意", 1);
					is_empty = true;
				}else {
					is_empty = false;
				}
				if(is_empty == false) {
					client.sendMessage(userName + ":" + field1.getText());// 向服务器发送文本内容
					field1.setText("");// 输入框置空
				}				
			}
		});

		// 开启窗口监听
		this.addWindowListener(new WindowAdapter() {
			// 窗口关闭时
			public void windowClosing(WindowEvent atg0) {
				int op = JOptionPane.showConfirmDialog(ClientFrame.this,
						"确定要退出聊天室吗?", "确定", JOptionPane.YES_NO_OPTION);// 弹出提示框
				if (op == JOptionPane.YES_OPTION) {// 如果选择是
					client.sendMessage("%EXIT%:" + userName);// 发送消息
					try {
						Thread.sleep(200);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					client.close();// 关闭客户端连接
					System.exit(0);// 关闭程序
				}
			}
		});
	}

	private class ReadMessageThread extends Thread {
		public void run() {
			while (true) {
				String str = client.reciveMessage();// 客户端收到服务器发来的文本内容
				area.append(str + "\n");// 向文本框添加文本内容
			}
		}
	}

	
	public static void main(String[] args) {
		new ClientFrame().showMe();
	}
}

客户端

// ChatRoomClient.java
package client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Vector;

import javax.swing.JOptionPane;

public class ChatRoomClient {
	Socket s;// 客户端套接字

	BufferedReader br;// 读取字节流

	PrintWriter pw;// 写入字节流
	

	public ChatRoomClient(String host, int port) throws UnknownHostException,
			IOException {
		s = new Socket(host, port);// 连接服务器
		br = new BufferedReader(new InputStreamReader(s.getInputStream()));// 字节流读取套接字输入流
		pw = new PrintWriter(s.getOutputStream());// 字节流写入套接字输出流
	}
	
	
	public void sendMessage(String str) {// 发送消息
		
		pw.println(str);
		pw.flush();
	}

	public String reciveMessage() {// 获取消息
		try {
			String xx = br.readLine();
			return xx;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	public void close() {// 关闭套接字连接
		try {
			s.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

服务器

// ChatRoomServer.java
package server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;

public class ChatRoomServer {
	ServerSocket serversocket;//服务器套接字

	HashSet<Socket> allSockets;//客户端套接字集合

	public ChatRoomServer() {
		try {
			serversocket = new ServerSocket(5678);//开启服务器5678接口
						
		} catch (IOException e) {
			e.printStackTrace();
		}
		allSockets = new HashSet<Socket>();//实例化客户端套接字结合
	}
	
	
	public void startService() throws IOException {
		System.out.println("服务器已成功开启");
		while (true) {
			Socket s = serversocket.accept();//获得一个客户端的连接
			System.out.println("用户已进入聊天室");
			allSockets.add(s);//将客户端连接的套接字放到集合中
			new ServerThread(s).start();//为此客户端单独创建一个事务处理线程
		}
	}

	private class ServerThread extends Thread {//线程类
		Socket s;

		public ServerThread(Socket s) {//通过构造方法获取客户端连接
			this.s = s;
		}

		public void run() {
			BufferedReader br = null;

			try {
				br = new BufferedReader(new InputStreamReader(
						s.getInputStream()));//将客户端套接字输入流转换为字节流读取
				while (true) {//无限循环
					String str = br.readLine();//读取到一行之后,则赋值给字符串
					if (str.indexOf("%EXIT%") == 0) {//如果文本内容中包括"%EXIT%"
						allSockets.remove(s);//集合删除此客户端连接
						sendMessageTOAllClient("-" + str.split(":")[1]
								+ "-已退出聊天室");//服务器向所有客户端接口发送退出通知
						s.close();//关闭此客户端连接
						return;//结束循环

					}
					sendMessageTOAllClient(str);//向所有客户端此客户端发来的文本信息
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		public void sendMessageTOAllClient(String message) throws IOException {//向所有客户端发送文本内容
			Date date = new Date();//创建时间类
			SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");//在文本后面添加时间
			System.out.println(message + "\t[" + df.format(date) + "]");
			for (Socket s : allSockets) {//循环集合中所有的客户端连接
				PrintWriter pw = new PrintWriter(s.getOutputStream());//创建输出流
				pw.println(message + "\t[" + df.format(date) + "]");//输写入文本内容
				pw.flush();//输出流刷新
			}
		}
	}

	public static void main(String[] args) {
		try {
			new ChatRoomServer().startService();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

需要详细报告或者有问题可以加QQ: 2953094905

here

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-07-26 12:23:00  更:2021-07-26 12:24:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 17:50:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码