`

基于socket的c/s聊天系统

阅读更多

在学习socket的时候,通过查找资料,和自己的学习,花了一个星期写出了这个模型,尽管功能和不太强大,还有点bug,但至少体现了socket的基本思想。部分代码省略了

客户端口,可以在client.ini 中配置

功能:
1.  用socket实现client/server的通信,服务端口8888;(配置文件)

2.  提供聊天的GUI,用Java Application实现,包括一个主窗口以及聊天窗口;(Swing)

3. 可实现一对多的聊天,每一个连接打开一个新的聊天窗口;(Thread)

4. 服务器端显示连接到客户端的IP地址,连接人数,以及在线客户的聊天记录

5. 客户端显示服务器IP地址,本机IP地址,和连接服务器的人数,以及当前客户的聊天记录

6. 关闭服务器,客户端连接失败,信息发送不出去; 

7. 关闭客户端,服务器显示离开的客户端的IP地址;

8. 通过文件配置读server的端口,和客户端的IP,Port;

9. 具有发送文本约束性。

1.服务器端

public class ChatServer extends JFrame implements Runnable, ActionListener {
	private JTextArea taOther;
	private JScrollPane pnOther;
	private JMenuItem version;
	private JMenuItem quit;
	private JMenu exitmn;
	private JMenu helpmn;
	private JMenuItem newmn;
	private JMenu filemn;
	private JMenuBar menuBar;
	private static final long serialVersionUID = 1L;
	private JTextArea taMessage;
	private JScrollPane pnMessage;
	private ServerSocket server; // 定义服务器端套接字
	private BManager bMan = new BManager();

	/**
	 * @param title
	 */
	public ChatServer(String title) {
		super(title);
		initialize();
	}

	/**
	 * 启动服务器
	 * 
	 */
	public void startServer() {
		try {
			// XXX 读取服务器端配置文件
			// 格式化代码
			BufferedReader br = new BufferedReader(new FileReader("server.ini"));
			// 产生读属性文件的对象
			Properties properties = new Properties();
			// 加载读文件的数据
			properties.load(br);
			// 从属性对象中取出对应的值
			String port = properties.getProperty("port");
			server = new ServerSocket(Integer.parseInt(port));
			taOther.append("服务器套接字创建完毕.\n");
			taOther.append("主机IP地址:"
					+ InetAddress.getLocalHost().getHostAddress() + "\n");
			taOther.append("等待客户机连接……" + "\n");
			while (true) {
				Socket socket = server.accept();

				taOther.append("客户IP地址:" + socket.getInetAddress() + "\n");
				// 创建并运行与客户机通信的线程
				new Chat_Thread(socket).start();
				// 向消息广播者列表添加socket
				bMan.add(socket);
				// 消息广播者向所有客户机传送当前连接人数
				bMan.sendClientInfo();
			}
		} catch (Exception e) {
			taOther.append(("服务器已经被启用,不能再被启用"));
		}
	}

	public static void main(String[] args) {

		ChatServer server = new ChatServer("聊天服务器");
		server.setVisible(true);
		server.startServer();
	}

	/**
	 * 与客户机通信的线程类
	 * 
	 */

	class Chat_Thread extends Thread {
		Socket socket;
		private BufferedReader reader;
		private PrintWriter writer;

		public Chat_Thread(Socket socket) {
			this.socket = socket;
		}

		@Override
		public void run() {
			try {
				// 从输出流获取消息
				reader = new BufferedReader(new InputStreamReader(socket
						.getInputStream()));
				writer = new PrintWriter(socket.getOutputStream(), true);
				writer.flush();
				String msg;
				while ((msg = reader.readLine()) != null) {
					taMessage.append(msg.trim() + "\n");
					// 向所有客户机传送信息
					bMan.sendToAll(msg);
				}
			} catch (Exception e) {
			} finally {
				try {
					// 从消息广播者列表删除socket
					bMan.remove(socket);
					taOther.append("客户机" + socket.getInetAddress() + "离开"
							+ "\n");
					if (reader != null)
						reader.close();
					if (writer != null)
						writer.close();
					if (socket != null)
						socket.close();
					reader = null;
					writer = null;
					socket = null;
					bMan.sendClientInfo();
				} catch (Exception e) {
				}
			}
		}
	}

	/**
	 * 消息广播者类,继承Vector类
	 * 
	 * 
	 */
	class BManager extends Vector {
		public BManager() {
		}

		/**
		 * 添加套接字
		 * 
		 * @param sock
		 * 
		 */
		public void add(Socket sock) {
			super.add(sock);
		}

		/**
		 * 删除套接字
		 * 
		 * @param sock
		 */
		public void remove(Socket sock) {
			super.remove(sock);
		}

		/**
		 * 向所有客户机传送内容
		 * 
		 * @param msg
		 */
		public synchronized void sendToAll(String msg) {
			PrintWriter writer = null;
			Socket sock;
			for (int i = 0; i < size(); i++) {
				// 获取第i套接字
				sock = (Socket) elementAt(i);
				try {
					// 输出流刷空
					writer = new PrintWriter(sock.getOutputStream(), true);
				} catch (IOException ie) {
				}
				// 使用第i个套接字输出流,输出msg
				if (writer != null)
					writer.println(msg);

			}
		}

		/**
		 * 服务器和客户端同时显示当前聊天人数
		 * 
		 */
		public synchronized void sendClientInfo() {
			String info = "当前聊天人数:" + size();
			taOther.append(info + "\n");
			sendToAll(info);
		}
	}

	private void initialize() {
		setJMenuBar(getMainJMenuBar());
		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		setName("f");
		setSize(new Dimension(700, 500));
		getContentPane().add(getPnMessage(), BorderLayout.CENTER);
		getContentPane().add(getPnOther(), BorderLayout.EAST);
	}

	/**
	 * @return
	 */
	protected JScrollPane getPnMessage() {
		if (pnMessage == null) {
			pnMessage = new JScrollPane();
			pnMessage.setViewportView(getTaMessage());
		}
		return pnMessage;
	}

	/**
	 * @return
	 */
	protected JTextArea getTaMessage() {
		if (taMessage == null) {
			taMessage = new JTextArea();
			taMessage.setBackground(new Color(220, 220, 220));
			taMessage.setEditable(false);
		}
		return taMessage;
	}

	/**
	 * @return
	 */
	/**
	 * @return
	 */

	@Override
	public void run() {
		// TODO Auto-generated method stub

	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		if (e.getSource() == getQuit()) {
			System.exit(0);
		}
	}

	/**
	 * @return
	 */
	protected JMenuBar getMainJMenuBar() {
		if (menuBar == null) {
			menuBar = new JMenuBar();

			menuBar.add(getFilemn());
			menuBar.add(getHelpmn());
			menuBar.add(getExitmn());
		}
		return menuBar;
	}

	/**
	 * @return
	 */
	protected JMenu getFilemn() {
		if (filemn == null) {
			filemn = new JMenu();
			filemn.setText("文件");
			filemn.add(getNewmn());
		}
		return filemn;
	}

	/**
	 * @return
	 */
	protected JMenuItem getNewmn() {
		if (newmn == null) {
			newmn = new JMenuItem();
			newmn.setText("新建");
		}
		return newmn;
	}

	/**
	 * @return
	 */
	protected JMenu getHelpmn() {
		if (helpmn == null) {
			helpmn = new JMenu();
			helpmn.setText("帮助");
			helpmn.add(getVersion());
		}
		return helpmn;
	}

	/**
	 * @return
	 */
	protected JMenu getExitmn() {
		if (exitmn == null) {
			exitmn = new JMenu();
			exitmn.setText("退出");
			exitmn.add(getQuit());
		}
		return exitmn;
	}

	/**
	 * @return
	 */
	protected JMenuItem getQuit() {
		if (quit == null) {
			quit = new JMenuItem();
			quit.addActionListener(this);
			quit.setText("关闭");
		}
		return quit;
	}

	/**
	 * @return
	 */
	protected JMenuItem getVersion() {
		if (version == null) {
			version = new JMenuItem();
			version.setText("版本");
		}
		return version;
	}

	/**
	 * @return
	 */
	protected JScrollPane getPnOther() {
		if (pnOther == null) {
			pnOther = new JScrollPane();
			pnOther.setViewportView(getTaOther());
		}
		return pnOther;
	}

	/**
	 * @return
	 */
	protected JTextArea getTaOther() {
		if (taOther == null) {
			taOther = new JTextArea();

			taOther.setEditable(false);
		}
		return taOther;
	}
}

 

2.客户端

public class ChatClient extends JFrame implements Runnable, ActionListener {

	private JTextArea tauser;
	private JScrollPane userpn;
	private JScrollPane viewpn;
	private JMenuItem versionmn;
	private JMenuItem shutupmn;
	private JTextArea ta;
	private JMenuItem connectmn;
	private JTextField nametf;
	private JTextField sendtf;
	private JButton sendbtn;
	private JPanel panel;
	private JMenu helpmn;
	private JMenu quitmn;
	private JMenu newmn;
	private JMenuBar menuBar;
	private Socket socket;
	private BufferedReader reader;
	private PrintWriter writer;
	private boolean runnable = true;

	public boolean getRunnable() {
		return runnable;
	}

	public void stop() {
		runnable = false;
	}

	/**
	 * 客户端主程序
	 * 
	 * @param args
	 */
	public static void main(String args[]) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					ChatClient client = new ChatClient();
					client.setVisible(true);
					client.connect();// 连接服务器
				} catch (Exception e) {
					// e.printStackTrace();
				}
			}
		});
	}

	/**
	 * 添加动作事件监听器
	 * 
	 */

	public void actionPerformed(ActionEvent e) {
		// 监听发送按钮和输入信息文本框的事件
		if (e.getSource() == getSendtf() || e.getSource() == getSendbtn()) {
			// 如果输入昵称为空,弹出警告框
			if (nametf.getText().equals("")) {
				JOptionPane.showMessageDialog(null, "请输入昵称!", "警告",
						JOptionPane.ERROR_MESSAGE);
			}
			// 如果输入的内容为空,弹出警告框
			else if (sendtf.getText().equals("")) {
				JOptionPane.showMessageDialog(null, "输入内容不能为空!", "警告",
						JOptionPane.ERROR_MESSAGE);
			}
			// 否则向文本框发送输入的内容
			else {
				writer.println(nametf.getText().trim() + " : "
						+ sendtf.getText().trim());
				sendtf.setText("");// 清除sendBox 内容
			}
		}
		// 关闭客户端事件
		if (e.getSource() == getShutupmn()) {
			try {
				this.stop();
				socket.close();
			} catch (Exception e1) {
				// e1.printStackTrace();
				System.exit(0);
			}
			System.exit(0);
		}
		// 版本事件
		if (e.getSource() == getVersionmn()) {
			Version v = new Version();
			v.show();
		}

		if (e.getSource() == getNewmn()) {
			ChatClient client = null;
			// return;
			client.connect();
		}

	}

	/**
	 * 客户端连接服务器
	 * 
	 */
	private void connect() {
		try {
			// 读文件
			// 格式化代码
			BufferedReader rd = new BufferedReader(new FileReader("client.ini"));
			// 产生读属性文件的对象
			Properties properties = new Properties();
			// 加载读文件的数据
			properties.load(rd);
			// 从属性对象中取出key对应的值

			String ip = (String) properties.get("IP");
			String port = (String) properties.get("port");
			// 客户端ip,port
			socket = new Socket(ip, Integer.parseInt(port));
			reader = new BufferedReader(new InputStreamReader(socket
					.getInputStream()));
			writer = new PrintWriter(socket.getOutputStream(), true);
			writer.flush();
			new Thread(this).start();
			tauser.append("连接服务器成功!" + "\n");
			tauser.append("本机地址:" + InetAddress.getLocalHost().getHostAddress()
					+ "\n");
			tauser.append("服务器地址:" + socket.getInetAddress() + "\n");
		} catch (Exception e) {
			// e.printStackTrace();
			tauser.append("服务器未启动,请先启动服务器!");
		}
	}

	/**
	 * 创建客户端界面
	 * 
	 */
	public ChatClient() {
		super();
		setBounds(100, 100, 500, 375);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		initialize();

	}

	private void initialize() {
		setTitle("客户机");
		setJMenuBar(getMainJMenuBar());
		getContentPane().add(getPanel(), BorderLayout.SOUTH);
		getContentPane().add(getNametf(), BorderLayout.NORTH);
		getContentPane().add(getViewpn());
		getContentPane().add(getUserpn(), BorderLayout.EAST);
	}

	/**
	 * @return 菜单栏
	 */
	protected JMenuBar getMainJMenuBar() {
		if (menuBar == null) {
			menuBar = new JMenuBar();
			menuBar.add(getNewmn());
			menuBar.add(getHelpmn());
			menuBar.add(getQuitmn());
		}
		return menuBar;
	}

	/**
	 * @return 新建
	 */
	protected JMenu getNewmn() {
		if (newmn == null) {
			newmn = new JMenu();
			newmn.setText("新建");
			newmn.add(getConnectmn());
		}
		return newmn;
	}

	/**
	 * @return 退出
	 */
	protected JMenu getQuitmn() {
		if (quitmn == null) {
			quitmn = new JMenu();
			quitmn.addActionListener(this);
			quitmn.setText("退出");
			quitmn.add(getShutupmn());
		}
		return quitmn;
	}

	/**
	 * @return 帮助
	 */
	protected JMenu getHelpmn() {
		if (helpmn == null) {
			helpmn = new JMenu();
			helpmn.setText("帮助");
			helpmn.add(getVersionmn());
		}
		return helpmn;
	}

	/**
	 * @return 面板
	 */
	protected JPanel getPanel() {
		if (panel == null) {
			panel = new JPanel();
			panel.setLayout(new BorderLayout());
			panel.add(getSendbtn(), BorderLayout.EAST);
			panel.add(getSendtf());
		}
		return panel;
	}

	/**
	 * @return 发送
	 */
	protected JButton getSendbtn() {
		if (sendbtn == null) {
			sendbtn = new JButton();
			sendbtn.addActionListener(this);
			sendbtn.setText("发送");
		}
		return sendbtn;
	}

	/**
	 * @return 发送文本框
	 */
	protected JTextField getSendtf() {
		if (sendtf == null) {
			sendtf = new JTextField();
		}
		return sendtf;
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		while (runnable) {
			try {
				// 从输入流读取数据,然后加至msgView

				ta.append(reader.readLine().trim() + "\n");

			} catch (IOException ie) {

				// tauser.append("服务器已关闭,请重新连接!" + "\n");
				// tauser.append("");
			}
		}
		tauser.append("服务器已关闭,请重新连接!" + "\n");
	}

	/**
	 * @return 姓名文本框
	 */
	protected JTextField getNametf() {
		if (nametf == null) {
			nametf = new JTextField();
		}
		return nametf;
	}

	/**
	 * @return 菜单新建连接
	 */
	protected JMenuItem getConnectmn() {
		if (connectmn == null) {
			connectmn = new JMenuItem();
			connectmn.addActionListener(this);
			connectmn.setText("新建连接");
		}
		return connectmn;
	}

	/**
	 * @return 信息输入文本框
	 */
	protected JTextArea getTa() {
		if (ta == null) {
			ta = new JTextArea();
			ta.setBackground(new Color(250, 240, 230));
			ta.setEditable(false);
		}
		return ta;
	}

	/**
	 * @return 菜单关闭
	 */
	protected JMenuItem getShutupmn() {
		if (shutupmn == null) {
			shutupmn = new JMenuItem();
			shutupmn.addActionListener(this);
			shutupmn.setText("关闭");
		}
		return shutupmn;
	}

	/**
	 * @return 菜单版本
	 */
	protected JMenuItem getVersionmn() {
		if (versionmn == null) {
			versionmn = new JMenuItem();
			versionmn.addActionListener(this);
			versionmn.setText("版本");
		}
		return versionmn;
	}

	/**
	 * @return 消息面板
	 */
	protected JScrollPane getViewpn() {
		if (viewpn == null) {
			viewpn = new JScrollPane();
			viewpn.setViewportView(getTa());
		}
		return viewpn;
	}

	/**
	 * @return 信息面板
	 */
	protected JScrollPane getUserpn() {
		if (userpn == null) {
			userpn = new JScrollPane();
			userpn.setViewportView(getTauser());
		}
		return userpn;
	}

	/**
	 * @return 文本用户
	 */
	protected JTextArea getTauser() {
		if (tauser == null) {
			tauser = new JTextArea();
			tauser.setEditable(false);
		}
		return tauser;
	}
}

 

 3.版本

public class Version extends JFrame implements ActionListener {

	private JLabel version10betaLabel;

	/**
	 * 版本框架
	 * 
	 * @param args
	 */
	public static void main(String args[]) {

		Version frame = new Version();
		frame.setVisible(true);

	}

	/**
	 * Create the frame
	 */
	public Version() {
		super();
		setBounds(60, 60, 210, 198);
		initialize();

	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub

	}

	private void initialize() {
		getContentPane().add(getVersion10betaLabel(), BorderLayout.CENTER);
	}

	/**
	 * @return
	 */
	protected JLabel getVersion10betaLabel() {
		if (version10betaLabel == null) {
			version10betaLabel = new JLabel();
			version10betaLabel.setText("Version:1.0Beta 设计者:mhm");
		}
		return version10betaLabel;
	}

}

 

2
0
分享到:
评论

相关推荐

    socket c/s聊天软件

    本篇将详细讲解基于Socket的C/S聊天软件及其相关知识点。 首先,让我们理解什么是Socket。Socket在计算机网络中是一种编程接口,它允许应用程序通过网络发送和接收数据。在C/S架构中,服务器端创建Socket并监听特定...

    c++ socket  c/s 聊天室

    在实现C/S聊天室时,我们通常会遇到以下几个关键步骤: 1. **服务器端:** - **创建Socket:** 使用`socket()`函数创建一个Socket对象。 - **绑定:** 用`bind()`函数将Socket与特定IP地址和端口号关联。 - **...

    基于SOCKET的C/S结构聊天室

    【标题】基于SOCKET的C/S结构聊天室 在计算机网络通信中,C/S(Client/Server)架构是一种常见的通信模型,它由客户端和服务器端组成。在这个基于Java的聊天室项目中,我们利用了Socket编程来实现C/S架构,从而实现...

    基于Socket的C/S通信层

    7. **应用示例**: 基于Socket的C/S通信层可以应用于多种网络应用,如在线游戏、文件传输、远程登录系统、实时聊天软件等。这些应用需要在多个设备间进行高效、稳定的数据交换。 总的来说,"基于Socket的C/S通信层...

    基于Java实现C/S架构的聊天系统

    在本项目中,我们探讨的是一个基于Java实现的C/S(客户端/服务器)架构的聊天系统。这个系统利用了Java的非阻塞I/O(NIO)机制,Socket通信以及多线程IO操作来实现一系列的功能,包括好友管理、聊天交互和文件传输,...

    Java实现C/S架构的聊天系统

    在本文中,我们将深入探讨如何使用Java来实现一个基于C/S(客户端/服务器)架构的聊天系统。这个系统利用了NIO(非阻塞I/O)机制、Socket通信以及多线程IO操作,实现了诸如好友管理、聊天交互以及文件传输等核心功能...

    基于C/S的类似QQ的聊天程序(c#)

    【标题】"基于C/S的类似QQ的聊天程序(c#)" 涉及的核心知识点是构建一个客户端/服务器(C/S)架构的即时通讯软件,使用C#编程语言,并借鉴了QQ的设计元素。C/S架构是一种典型的两层或三层网络应用模式,其中客户端...

    基于C/S模式的聊天程序

    在本例中,"ChatApplicationSLN"可能是一个包含C/S聊天程序所有源代码和资源的解决方案。打开这个文件,你将能看到项目的组织结构,包括客户端和服务器端的源代码文件,以及其他可能的辅助文件。 总结,通过这个...

    基于C/S模式的Java聊天室

    【标题】"基于C/S模式的Java聊天室"是一个典型的网络通信项目,它采用客户机/服务器(Client/Server,简称C/S)架构,通过Java编程语言实现。在这个模式下,客户端作为用户交互的界面,负责发送和接收聊天信息;而...

    基于C/S架构的聊天系统的实现

    在本项目"基于C/S架构的聊天系统的实现"中,我们探讨了如何运用Java语言和相关技术来构建这样一个系统,旨在提供好友管理、实时聊天以及文件传输等功能,这对于学习和提升Java编程技能具有很高的价值。 首先,C/S...

    基于C/s模式简单聊天系统

    【标题】"基于C/S模式简单聊天系统"指的是在客户端/服务器(Client/Server, C/S)架构下设计和实现的一个简易聊天应用。C/S模式是计算机网络中常见的一种架构,其中客户端(Client)作为用户界面,负责与用户交互,...

    基于C/S模式的JAVA聊天室

    【基于C/S模式的JAVA聊天室】是一种网络通信应用程序,它使用了客户端/服务器(Client/Server,简称C/S)架构。在这个系统中,客户端是用户使用的界面,用于发送和接收消息,而服务器端则是处理客户端请求并进行相应...

    基于C/S结构的Java局域网聊天系统包含MySQL数据库

    《构建基于C/S结构的Java局域网聊天系统与MySQL数据库整合详解》 在信息技术领域,C/S(Client/Server)架构是一种常见的分布式应用模式,它将应用逻辑分为客户端和服务端两部分。在这个架构中,客户端负责用户交互...

    基于C/S模式的聊天系统

    基于C/S模式的聊天系统用C/S模拟的聊天室很简洁很方便

    计算机网络 基于C/S模式的简单聊天程序

    4. **TCP/IP协议**:在C/S聊天程序中,通常使用传输控制协议/因特网协议(TCP/IP)进行数据传输,保证数据的可靠性和顺序性。TCP提供了面向连接的服务,确保消息完整无误地送达。 5. **多线程**:为了实现同时处理...

    基于c/s架构的JAVA聊天程序

    在IT领域,C/S(Client/Server)架构是一种常见的分布式应用结构,主要用于构建网络应用程序,如我们这里的"基于C/S架构的JAVA聊天程序"。在这个系统中,客户端(Client)负责用户交互,而服务器端(Server)处理...

    socket b/s架构

    此外,许多现代Web服务,如RESTful API、WebSocket等,也是基于socket通信实现的。 总之,通过Linux下的socket编程实现B/S架构的通信涉及到了网络编程、HTTP协议、服务器端和客户端设计等多个方面的知识。理解并...

    java版聊天程序聊天界面 C/S聊天室 UDP通信 添加删除好友,设置个人信息,GUI,socket,

    java版QQ,java编写的聊天软件,完全模仿QQ,具有强大的聊天界面,可以手动添加好友,删除好友,设置个人信息,搜索好友,基于UDP数据报方式实现两天主机之间的通话。视频,音频,短信功能没有实现,但已经做好接口...

    基于socket的聊天系统设计

    《网络程序设计》课程设计中的基于socket的聊天系统是一个典型的网络通信应用,它利用socket接口来构建客户端和服务器之间的通信链路。socket是Internet上的进程间通信机制,它允许两个运行在网络不同位置的程序通过...

    面试作品java c/s聊天室带简单界面

    【标题】"面试作品java c/s聊天室带简单界面"是一个基于Java的客户端/服务器(C/S)架构的聊天应用程序,它集成了图形用户界面(GUI)、套接字通信、文件输入/输出(File IO)以及多线程技术。这个项目展示了开发者...

Global site tag (gtag.js) - Google Analytics