在学习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; } }
相关推荐
本篇将详细讲解基于Socket的C/S聊天软件及其相关知识点。 首先,让我们理解什么是Socket。Socket在计算机网络中是一种编程接口,它允许应用程序通过网络发送和接收数据。在C/S架构中,服务器端创建Socket并监听特定...
在实现C/S聊天室时,我们通常会遇到以下几个关键步骤: 1. **服务器端:** - **创建Socket:** 使用`socket()`函数创建一个Socket对象。 - **绑定:** 用`bind()`函数将Socket与特定IP地址和端口号关联。 - **...
【标题】基于SOCKET的C/S结构聊天室 在计算机网络通信中,C/S(Client/Server)架构是一种常见的通信模型,它由客户端和服务器端组成。在这个基于Java的聊天室项目中,我们利用了Socket编程来实现C/S架构,从而实现...
7. **应用示例**: 基于Socket的C/S通信层可以应用于多种网络应用,如在线游戏、文件传输、远程登录系统、实时聊天软件等。这些应用需要在多个设备间进行高效、稳定的数据交换。 总的来说,"基于Socket的C/S通信层...
在本项目中,我们探讨的是一个基于Java实现的C/S(客户端/服务器)架构的聊天系统。这个系统利用了Java的非阻塞I/O(NIO)机制,Socket通信以及多线程IO操作来实现一系列的功能,包括好友管理、聊天交互和文件传输,...
在本文中,我们将深入探讨如何使用Java来实现一个基于C/S(客户端/服务器)架构的聊天系统。这个系统利用了NIO(非阻塞I/O)机制、Socket通信以及多线程IO操作,实现了诸如好友管理、聊天交互以及文件传输等核心功能...
【标题】"基于C/S的类似QQ的聊天程序(c#)" 涉及的核心知识点是构建一个客户端/服务器(C/S)架构的即时通讯软件,使用C#编程语言,并借鉴了QQ的设计元素。C/S架构是一种典型的两层或三层网络应用模式,其中客户端...
在本例中,"ChatApplicationSLN"可能是一个包含C/S聊天程序所有源代码和资源的解决方案。打开这个文件,你将能看到项目的组织结构,包括客户端和服务器端的源代码文件,以及其他可能的辅助文件。 总结,通过这个...
【标题】"基于C/S模式的Java聊天室"是一个典型的网络通信项目,它采用客户机/服务器(Client/Server,简称C/S)架构,通过Java编程语言实现。在这个模式下,客户端作为用户交互的界面,负责发送和接收聊天信息;而...
在本项目"基于C/S架构的聊天系统的实现"中,我们探讨了如何运用Java语言和相关技术来构建这样一个系统,旨在提供好友管理、实时聊天以及文件传输等功能,这对于学习和提升Java编程技能具有很高的价值。 首先,C/S...
【标题】"基于C/S模式简单聊天系统"指的是在客户端/服务器(Client/Server, C/S)架构下设计和实现的一个简易聊天应用。C/S模式是计算机网络中常见的一种架构,其中客户端(Client)作为用户界面,负责与用户交互,...
【基于C/S模式的JAVA聊天室】是一种网络通信应用程序,它使用了客户端/服务器(Client/Server,简称C/S)架构。在这个系统中,客户端是用户使用的界面,用于发送和接收消息,而服务器端则是处理客户端请求并进行相应...
《构建基于C/S结构的Java局域网聊天系统与MySQL数据库整合详解》 在信息技术领域,C/S(Client/Server)架构是一种常见的分布式应用模式,它将应用逻辑分为客户端和服务端两部分。在这个架构中,客户端负责用户交互...
基于C/S模式的聊天系统用C/S模拟的聊天室很简洁很方便
4. **TCP/IP协议**:在C/S聊天程序中,通常使用传输控制协议/因特网协议(TCP/IP)进行数据传输,保证数据的可靠性和顺序性。TCP提供了面向连接的服务,确保消息完整无误地送达。 5. **多线程**:为了实现同时处理...
在IT领域,C/S(Client/Server)架构是一种常见的分布式应用结构,主要用于构建网络应用程序,如我们这里的"基于C/S架构的JAVA聊天程序"。在这个系统中,客户端(Client)负责用户交互,而服务器端(Server)处理...
此外,许多现代Web服务,如RESTful API、WebSocket等,也是基于socket通信实现的。 总之,通过Linux下的socket编程实现B/S架构的通信涉及到了网络编程、HTTP协议、服务器端和客户端设计等多个方面的知识。理解并...
java版QQ,java编写的聊天软件,完全模仿QQ,具有强大的聊天界面,可以手动添加好友,删除好友,设置个人信息,搜索好友,基于UDP数据报方式实现两天主机之间的通话。视频,音频,短信功能没有实现,但已经做好接口...
《网络程序设计》课程设计中的基于socket的聊天系统是一个典型的网络通信应用,它利用socket接口来构建客户端和服务器之间的通信链路。socket是Internet上的进程间通信机制,它允许两个运行在网络不同位置的程序通过...
【标题】"面试作品java c/s聊天室带简单界面"是一个基于Java的客户端/服务器(C/S)架构的聊天应用程序,它集成了图形用户界面(GUI)、套接字通信、文件输入/输出(File IO)以及多线程技术。这个项目展示了开发者...