当前位置: 首页 > news >正文

多人聊天

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

 

package com.socketForm;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.IOError;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Scanner;

import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.ListModel;
import javax.swing.border.TitledBorder;
/**
 * 聊天程序服务器窗口
 * @author dingzhen
 * @version 2016-03-09
 */
public class ServerForm extends JFrame{
 private static final long serialVersionUID = 1L;
 private static final int PORT = 9090;        //端口号
 private JTextArea area;            //用户放用户信息的显示区
 private DefaultListModel lm;          //列表对像,用户保存用户登录信息
 private Map<String,Object> usersMap = new HashMap<String, Object>(); //保存所有在线用户的名称和Socket
 public ServerForm() throws Exception{
  area = new JTextArea();
  area.setEditable(false);
  lm = new DefaultListModel();
  getContentPane().add(new JScrollPane(area));
  
  JList list= new JList(lm);
  JScrollPane jc = new JScrollPane(list);
  jc.setPreferredSize(new Dimension(100,this.getHeight()));
  jc.setBorder(new TitledBorder("在线"));
  getContentPane().add(jc,BorderLayout.EAST);
  JMenuBar bar = new JMenuBar();         //声明一组菜单
  JMenu    m   = new JMenu("控制");
  bar.add(m);
  m.setMnemonic('C');
  final JMenuItem run = new JMenuItem("开启");
  run.setAccelerator(KeyStroke.getKeyStroke('R',KeyEvent.CTRL_MASK));  //设置快捷键
  run.setActionCommand("run");
  m.add(run);

  
  m.addSeparator();
  JMenuItem exit = new JMenuItem("退出");
  exit.setAccelerator(KeyStroke.getKeyStroke('E',KeyEvent.CTRL_MASK));
  exit.setActionCommand("exit");
  m.add(exit);
  setJMenuBar(bar);
  
  ActionListener al = new ActionListener(){      //添加一个内部类,以启动服务器
   public void actionPerformed(ActionEvent e) {
    if(e.getActionCommand().equals("run")){
     startServer();
     run.setEnabled(false);
    }else{
     System.exit(0);
    }
   }
  };
  run.addActionListener(al);
  exit.addActionListener(al);
  
  final int winWidth  = 500;
  final int winHeight = 400;
     Toolkit toolkit = Toolkit.getDefaultToolkit();
     int width  = (int)toolkit.getScreenSize().getWidth();
     int height = (int)toolkit.getScreenSize().getHeight();
     setTitle("这是服务器");
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  setBounds(width/2-winWidth/2,height/2-winHeight/2,winWidth, winHeight);   //在屏幕的中间显示
  setVisible(true);
  
 }
 public static void main(String[] args) throws Exception {
  JFrame.setDefaultLookAndFeelDecorated(true);
  new ServerForm();
 }
 /**
  * 启动服务器
  */
 public void startServer(){
  try{
   System.err.println("启动服务...");
   ServerSocket server = new ServerSocket(PORT);
   area.append("启动服务:"+server);
   new ServerThread(server).start();
  }catch(Exception e){
   e.printStackTrace();
  }
 }
 /**
  * 启动服务的线程
  */
 class ServerThread extends Thread{
  private ServerSocket server;
  public ServerThread(ServerSocket server) {
   this.server = server;
  }
  public void run() {
   try{
    while(true){
     Socket socketClient = server.accept();      //等待获取客户端的连接
     Scanner sc   = new Scanner(socketClient.getInputStream()); //获取用户端输入流
     if(sc.hasNextLine()){
      String userName = sc.nextLine();
      area.append("\r\n用户:["+userName+"]登录,"+socketClient);
      lm.addElement(userName);
      new ClientThread(socketClient);        //启动这个线程
      msgAll(userName);           //通知所有人有人登录
      msgSelf(socketClient);             //通知当前登录的人,有多少人在线
      usersMap.put(userName,socketClient);
      System.err.println("一个线程已经启动....");
     }
     
     
    }
   }catch(Exception e){
    e.printStackTrace();
   }
  }
 }
 /**
  * 服务器开始客户端的线程
  */
 class ClientThread extends Thread{
  private Socket client;
  public ClientThread(Socket client) {
   System.err.println("初始。。。。。");
   this.client = client;
   start();
  }
  public void run(){
   System.err.println("一个线程启动成功。。。。");
   try{
    Scanner sc = new Scanner(client.getInputStream());
    while(sc.hasNextLine()){   //这儿接收用户的信息,格式如下:命令@#给谁@#消息@#自己
     String msg = sc.nextLine();
     System.err.println(msg);
     String[] msgs = msg.split("@#");
     if(msgs[0].equals("exit")){       //结束此线程的运行,停止会话
      System.err.println("退出人:"+msgs[3]);    //还要通知甩有人有人退出,并删除所有人列表中的自己
      usersMap.remove(msgs[3]);      //从列表中删除此用户的信息
      lm.removeElement(msgs[3]);      //从服务器的显示列中删除
      area.append("\r\n用户["+msgs[3]+"]退出了。");
      sendExitMsgToAll(msgs);
      break;
     }else{
      sendMsgToSb(msgs);        //发消息给某人
     }
    }
   }catch(Exception e){
    e.printStackTrace();
   }
  }
 }
 /**
  * 通知所有人,有人登录
  * 写出信息的类型为:
  * 类型:通知(cmd)|消息(msg)@#谁的通知SomeBody@#消息文本MSG
  */
 private void msgAll(String userName){
  try{
   Iterator<Object> it = usersMap.values().iterator();
   while(it.hasNext()){
    Socket s = (Socket)it.next();
    try{
     PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
     String msg = "msg@#server@#用户["+userName+"]登录了.";
     pw.println(msg);
     pw.flush();
     msg = "cmdAdd@#server@#"+userName;
     pw.println(msg);
     pw.flush();
    }catch(IOException e){
     e.printStackTrace();
    }
   }
  }catch(Exception e){
   e.printStackTrace();
  }
 }
 /**
  * 通知当前登录的人有多少人在线
  */
 private void msgSelf(Socket client){
  try{
   PrintWriter pw = new PrintWriter(client.getOutputStream(),true);
   Iterator<String> it = usersMap.keySet().iterator();
   while(it.hasNext()){
    String msg = "cmdAdd@#server@#"+it.next();
    pw.println(msg);
   }
  }catch(IOException e){
   e.printStackTrace();
  }
 }
 /**
  * 发消息给某人
  */
 private void sendMsgToSb(String[] msgs) throws IOException{
  if(msgs[1].equals("全部")){           //发消息给所有人
   Iterator<String> userNames = usersMap.keySet().iterator();
   while(userNames.hasNext()){
    String userName = userNames.next();
    if(!userName.equals(msgs[3])){        //如果不是自己
     Socket s = (Socket)usersMap.get(userName);
     PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
     String str = "msg@#"+msgs[3]+"@#"+msgs[2];
     pw.println(str);
     pw.flush();
    }
   }
  }else{
   Socket s = (Socket)usersMap.get(msgs[1]);       
   PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
   String str = "msg@#"+msgs[3]+"@#"+msgs[2];
   pw.println(str);
   pw.flush();
  }
 }
 /**
  * 通知所有人有人退出
  */
 private void sendExitMsgToAll(String[] msgs) throws IOException{
  Iterator<String> userNames = usersMap.keySet().iterator();
  while(userNames.hasNext()){
   String userName = userNames.next();
   Socket s = (Socket)usersMap.get(userName);
   PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
   String str = "msg@#server@#用户["+msgs[3]+"]退出了。";
   pw.println(str);
   pw.flush();
   str = "cmdRed@#server@#"+msgs[3];
   pw.println(str);
   pw.flush();
  }
 }
}

package com.socketForm;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
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.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;
/**
 * 客户端程序
 * @author dingzhen
 * @version 2016-03-09
 */
public class ClientForm extends JFrame implements ActionListener{
 private static final long serialVersionUID = 1L;
 private static  String HOST = "127.0.0.1";       //服务器地址
 private static  int    PORT = 9090;         //端口号
 private JTextField userName;          //启用标识
 private DefaultListModel lm;          //在线用户列表
 private JList list;
 private JTextField msg;            //发消息框
 private JTextArea allMsg = new JTextArea();       //收消息框
 public ClientForm() throws Exception {
  addJMenuBar();              //设置菜单
  userName = new JTextField(10);
  JPanel  p= new JPanel();
  p.add(new JLabel("用户标识:"));
  p.add(userName);
  JButton conn = new JButton("连接");
  conn.setActionCommand("c");
  conn.addActionListener(this);
  p.add(conn);
  
  JButton exitBtn = new JButton("退出");
  exitBtn.setActionCommand("exit");
  exitBtn.addActionListener(this);
  p.add(exitBtn);
  p.setBorder(new LineBorder(Color.GRAY));
  //以下是中间的面板
  JPanel center = new JPanel(new BorderLayout());
  lm = new DefaultListModel();
  list = new JList(lm);
  lm.addElement("全部");
  list.setSelectedIndex(0);             //默认选中全部
  list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
  list.setVisibleRowCount(2);
  JScrollPane jc = new JScrollPane(list);
  jc.setBorder(new TitledBorder("在线"));
  jc.setPreferredSize(new Dimension(70,center.getHeight()));
  center.add(jc,BorderLayout.EAST);
  
  JPanel send  = new JPanel();
  send.add(new JLabel("消息:"));
  msg = new JTextField(20);
  send.add(msg);
  JButton sendBtn  = new JButton("发送");
  sendBtn.setActionCommand("send");
  sendBtn.addActionListener(this);
  send.add(sendBtn);
  center.add(send,BorderLayout.SOUTH);
  allMsg.setEditable(false);
  center.add(new JScrollPane(allMsg));
  Container c = getContentPane();
  c.add(p,BorderLayout.NORTH);
  c.add(center,BorderLayout.CENTER);
  addWindowListener(new WindowAdapter() {       //当用户退出时,先要通知所有人,有人退出
   public void windowClosing(WindowEvent arg0) {
    sendExitMsg();
   }
  });
  setBounds(300, 300, 400, 300);
  setVisible(true);
 }
 
 public static void main(String[] args) throws Exception {
  JFrame.setDefaultLookAndFeelDecorated(true);
  new ClientForm();
 }
 public void actionPerformed(ActionEvent e) {
  if(e.getActionCommand().equals("c")){
   System.err.println("连接...");
   connecting();
  }else if(e.getActionCommand().equals("send")){
   String msg = "on@#"+list.getSelectedValue()+"@#"+this.msg.getText()+"@#"+userName.getText();
   System.err.println(">发出的消息为:"+msg);
   pw.println(msg);
   pw.flush();
  }else if(e.getActionCommand().equals("exit")){    //用户要退出
   sendExitMsg();
  }
 }
 /**
  * 发送退出的消息
  */
 private void sendExitMsg(){
  if(client==null){
   System.exit(0);
   return;
  }
  String msg = "exit@#全部@#null@#"+userName.getText();
  System.err.println("退出:"+msg);
  pw.println(msg);
  pw.flush();
  System.exit(0);
 }
 /**
  * 创建一个用户连接
  */
 private Socket client;            //声明一个客户端的连接
 private PrintWriter pw;
 private void connecting(){
  try{
   System.err.println(HOST+","+PORT);
   client= new Socket(HOST,PORT);
   String userName = this.userName.getText();      //获取用户标识
   pw = new PrintWriter(client.getOutputStream(),true);
   pw.println(userName);
   this.setTitle("用户["+userName+"]在线...");
   new ClientThread().start();
  }catch(Exception e){
   e.printStackTrace();
  }
 }
 /**
  * 用以下线程来读取服务器发送来的信息
  */
 class ClientThread extends Thread{
  public void run() {
   try{
    Scanner sc = new Scanner(client.getInputStream());
    while(sc.hasNextLine()){
     String str = sc.nextLine();
     System.err.println("客户端接收到的消息 :"+str);
     String[] msg = str.split("@#");
     if(msg[0].equals("msg")){      //开头不是msg就是cmd命令
      if(msg[1].equals("server")){
       str = "[通知]:"+msg[2];
      }else{
       str = "["+msg[1]+"]说:"+msg[2];
      }
      allMsg.append("\r\n"+str);
     }else if(msg[0].equals("cmdAdd")){      //说明有人登录
      lm.addElement(msg[2]);
     }else if(msg[0].equals("cmdRed")){      //说明有人退出
      lm.removeElement(msg[2]);
     }
    }
   }catch(IOException e){
    e.printStackTrace();
   }
  }
 }
 /**
  * 添加菜单,控制选项,可以设置服务器及端口号
  */
 private void addJMenuBar(){
  JMenuBar bar = new JMenuBar();
  JMenu    m   = new JMenu("选项");
  JMenuItem mi = new JMenuItem("设置");
  JMenuItem help = new JMenuItem("帮助");
  mi.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent arg0) {
    final JDialog set = new JDialog(ClientForm.this,true);
    set.setBounds(ClientForm.this.getX(),ClientForm.this.getY(), 300, 100);
    set.setLayout(new FlowLayout());
    JButton btn = new JButton("设置");
    final JTextField host = new JTextField(10);
    host.setText("127.0.0.1");
    final JTextField port = new JTextField(5);
    port.setText("9090");
    btn.addActionListener(new ActionListener() {
     public void actionPerformed(ActionEvent arg0) {
      ClientForm.HOST = host.getText();
      ClientForm.PORT = Integer.parseInt(port.getText());
      System.err.println(ClientForm.HOST);
      set.dispose();   //关闭且销毁
     }
    });
    set.add(new JLabel("服务器:"));
    set.add(host);
    set.add(new JLabel(":"));
    set.add(port);
    set.add(btn);
    set.setVisible(true);
   }
  });
  help.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e) {
    JDialog set = new JDialog(ClientForm.this,true);
    set.setBounds(ClientForm.this.getX(),ClientForm.this.getY(), 300, 100);
    JLabel jl = new JLabel("版权所有@dingzhen 2016-03-09");
    set.add(jl);
    set.setVisible(true);
   }
  });
  bar.add(m);
  m.add(mi);
  m.add(help);
  this.setJMenuBar(bar);
 }
}

转载于:https://my.oschina.net/dtz/blog/633574

相关文章:

  • mysql5.5.48 多实例配置及启动脚本
  • java 验证码生成
  • 五大常用算法之五:分支限界法
  • Swift 中的函数(上)
  • IOS开发中UILabel单行、多行文本计算高度、宽度的技巧
  • 盲修瞎练路漫漫,名师点化三日成[转]
  • jsp 页面和 jsp标记
  • 给包文件增加注释
  • 纯手动编译安装LAMP,   cacti , nagios , zabbix
  • Maven学习 (一) 搭建Maven环境
  • 1、绪论
  • forward内部跳转 和redirect重定向跳转的区别
  • iOS版微软自拍App上架:自然美颜 上手简单
  • JAVA - 多线程 两种方法的比较
  • elasticsearch插件安装
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • conda常用的命令
  • Flannel解读
  • Golang-长连接-状态推送
  • JavaScript 是如何工作的:WebRTC 和对等网络的机制!
  • js ES6 求数组的交集,并集,还有差集
  • Laravel 实践之路: 数据库迁移与数据填充
  • OSS Web直传 (文件图片)
  • PaddlePaddle-GitHub的正确打开姿势
  • PHP 程序员也能做的 Java 开发 30分钟使用 netty 轻松打造一个高性能 websocket 服务...
  • webpack项目中使用grunt监听文件变动自动打包编译
  • 阿里云爬虫风险管理产品商业化,为云端流量保驾护航
  • 从setTimeout-setInterval看JS线程
  • 大快搜索数据爬虫技术实例安装教学篇
  • 欢迎参加第二届中国游戏开发者大会
  • 类orAPI - 收藏集 - 掘金
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 嵌入式文件系统
  • 使用 Node.js 的 nodemailer 模块发送邮件(支持 QQ、163 等、支持附件)
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • HanLP分词命名实体提取详解
  • Hibernate主键生成策略及选择
  • 阿里云ACE认证学习知识点梳理
  • #vue3 实现前端下载excel文件模板功能
  • (C语言)strcpy与strcpy详解,与模拟实现
  • (Matalb时序预测)PSO-BP粒子群算法优化BP神经网络的多维时序回归预测
  • (二)linux使用docker容器运行mysql
  • (二)windows配置JDK环境
  • (二)构建dubbo分布式平台-平台功能导图
  • (附源码)springboot青少年公共卫生教育平台 毕业设计 643214
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (论文阅读笔记)Network planning with deep reinforcement learning
  • (源码版)2024美国大学生数学建模E题财产保险的可持续模型详解思路+具体代码季节性时序预测SARIMA天气预测建模
  • (转)Linq学习笔记
  • (转)项目管理杂谈-我所期望的新人
  • .Net MVC + EF搭建学生管理系统
  • .NET NPOI导出Excel详解
  • .net 按比例显示图片的缩略图
  • .Net 路由处理厉害了
  • .NET关于 跳过SSL中遇到的问题