`
Sunshyfangtian
  • 浏览: 228723 次
  • 性别: Icon_minigender_1
  • 来自: 惠州
社区版块
存档分类
最新评论

一个简单的UDP聊天室

阅读更多

以下资料是从别处直接Copy的,为了方便查找使用,放到“毕设手记”里了

一个简单的使用UDP协议实现的联天室,附件中有Eclipse3.4调试的project。

由两个包组成:server 和 client

 

server包里有如下两个类:

 

package server;

import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Date;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class ServerFrame extends JFrame{

 private JTextArea allmsg;
 private JTextField currnum,totalnum,copyright,chatmsg;
 private JButton send;
 private JScrollPane js;
 int num1,num2,port;/*  -- num1:当前在线人数  num2:总上线人数  port:服务端口号 --*/
 
 private ServerSocket ss;
 
 ArrayList lists;//存放所有在线用户
 
 public ServerFrame()
 {
  super("聊天室服务器端");
  this.setSize(310,660);
  this.setLocation(200,50);
  
  lists = new ArrayList();
  
  num1 = num2 =0;
  port = 7777;
  
  currnum = new JTextField(" 当前在线人数: "+num1);
  currnum.setEnabled(false);
  
  totalnum = new JTextField(" 上线总人数: "+num2);
  totalnum.setEnabled(false);
  
  copyright = new JTextField("             -----  all copyright @ TOP-king  -----");
  copyright.setEnabled(false);  
  
  allmsg = new JTextArea();
  allmsg.append("                   --------------- 系统消息 --------------\n");
  allmsg.setEditable(false);
  allmsg.setLineWrap(true); //允许自动换行

  js = new JScrollPane(allmsg);//为JTextArea添加滚动条  

  
  chatmsg = new JTextField("在此输入系统信息");
  chatmsg.addActionListener(new ActionListener(){   

   public void actionPerformed(ActionEvent arg0) {
    String str = chatmsg.getText().trim();
    if(!"".equals(str))
      {sendmsg((new Date()).toLocaleString()+" -- 系统消息: "+str);chatmsg.setText("");}
    else
         JOptionPane.showMessageDialog(null, "消息不能为空","错误",JOptionPane.OK_OPTION);
    chatmsg.setText("");/*  -- 发送信息后,将输入栏中的信息清空 --  */
   }
  }); 
  
  send = new JButton("发送");
  send.addActionListener(new ActionListener(){   

   public void actionPerformed(ActionEvent arg0) {
    String str = chatmsg.getText().trim();
    if(!"".equals(str))
      {sendmsg((new Date()).toLocaleString()+" -- 系统消息: "+str);chatmsg.setText("");}
    else
         JOptionPane.showMessageDialog(null, "消息不能为空","错误",JOptionPane.OK_OPTION);
    chatmsg.setText("");/*  -- 发送信息后,将输入栏中的信息清空 --  */
   }
  });
  
  addcomponettocontainer();
  this.addWindowListener(new WindowAdapter(){
   public void windowClosing(WindowEvent we)
   {
    sendmsg("SYSTEM_CLOSED");/*  -- 向客户端发送服务器关闭信息 --  */
    destory();
   }
  });
  start(); /*  -- 启动连接服务 --  */
    
 }
 
 public void addcomponettocontainer()
 {
  Container c = this.getContentPane();
  c.setLayout(null);
  
  currnum.setBounds(20,15,130,20);
  totalnum.setBounds(155,15,125,20);
  js.setBounds(10,50,280,500);
  chatmsg.setBounds(10,560,180,30);
  send.setBounds(220,560,70,30);
  copyright.setBounds(10,600,280,20);
  
  c.add(currnum);
  c.add(totalnum);
  c.add(js);
  c.add(chatmsg);
  c.add(send);
  c.add(copyright);
  
  this.setVisible(true);
  this.setResizable(false);
 }
 
 
 /**  
  *  start()方法监听客户的连接
  *  并且保存客户端的相关信息EG:用户昵称、用户所使用的Socket
  *  用户连接到服务器成功之后,将其保存到用户列表中,并为该用户启动一个线程用于通信 */
 public void start()
 {
  boolean isStarted = false;/*  -- 用于标记服务器是否已经正常启动 --  */
  try {
   this.ss = new ServerSocket(port);
   isStarted = true;
   this.allmsg.append((new Date()).toLocaleString()+"    服务器启动 @ 端口: "+port+"\n");
   while(isStarted)
   {
    Socket client = this.ss.accept(); /*  -- 监听客户端的连接 --  */
    DataInputStream in = new DataInputStream(client.getInputStream());
    String name = in.readUTF();
    user u = new user();
    u.name = name;
    u.socket = client;
    lists.add(u); //将该用户加到列表中去
    num1++;
    num2++;
    currnum.setText(" 当前在线人数: "+num1);
    totalnum.setText(" 上线总人数: "+num2);
    this.allmsg.append((new Date()).toLocaleString()+" : "+u.name+" 登录 \n");
    new Thread(new ClientThread(u)).start();/*  -- 为该用户启动一个通信线程 --  */
   }
   
  } catch (IOException e) {
   System.out.println("服务器已经启动......");
   System.exit(0);
  }
 }

 /**
  * 通信线程主要功能包括:
  * 1.监听客户端输入的信息
  * 2.将接收到的信息转发给其他用户  */
 class ClientThread implements Runnable
 {
  user user = null;
  boolean isConnected = true;
  DataInputStream dis = null;
  DataOutputStream dos = null;
  
  public ClientThread(user u)
  {
      this.user = u; 
      try {
    this.dis = new DataInputStream(this.user.socket.getInputStream());
    this.dos = new DataOutputStream(this.user.socket.getOutputStream());
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
  
  public void run()
  {
   readmsg();
  }
  
  /*  -- 读取客户的聊天信息 --  */
   public void readmsg()
   {
    while(isConnected)
    {
     try {         
      String msg = dis.readUTF();
      if("quit&logout".equals(msg))//当用户关闭客户端窗口时,发送quit字符串 表示用户已经退出
      {
       num1--;       
       try{
        this.dis.close();
        this.dos.close();
        this.user.socket.close();
        this.isConnected = false;
       }catch(IOException ioe)
       {
        ioe.printStackTrace();
       }finally{
        this.isConnected = false;
        if(dis!=null) this.dis.close();
        if(dos!=null) this.dos.close();
        if(this.user.socket!=null) this.user.socket.close();
       }
       lists.remove(this.user);//从列表中删除该用户
       currnum.setText(" 当前在线人数: "+num1);
       allmsg.append((new Date()).toLocaleString()+"  : "+this.user.name+"  退出\n");
      }
      else
      sendmsg(msg);
     } catch (IOException e) {
      e.printStackTrace();
     }
   }
   }    
     
 }
   
 /*  -- 将信息进行转发 --  */
 public void sendmsg(String msg)
    {
     user us = new user();
     DataOutputStream os = null;
     if(lists.size()>0)
     {
      for(int i=0;i<lists.size();i++)
         {
             us = (user)lists.get(i);
             try {   
              os = new DataOutputStream(us.socket.getOutputStream());
        os.writeUTF(msg);
       } catch (IOException e) {
        e.printStackTrace();
       }
         }
     } 
     else
      JOptionPane.showMessageDialog(null, "当前无用户在线。发送消息失败","失败",JOptionPane.OK_OPTION);
    } 
 
    public void destory()
    {
     try {
   this.ss.close();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  this.dispose();
    }
    
 public static void main(String[] args)
 {
  new ServerFrame();
 }

}

 

 

 

package server;

import java.net.*;

public class user {

  String name;
  Socket socket;
}

 

 

 

client包里有如下两个类:

 

1.

 

package client;

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;

public class LoginFrame extends JFrame{
 private JTextField name;
 private JTextField ip;
 private JButton ok,cancle;
  
 public Socket socket;
 
 public LoginFrame()
 {
  super("登录框");
  this.setSize(400,80);
  this.setLocation(100,100);  
   
  name = new JTextField("昵称");   
  ip = new JTextField("127.0.0.1");
  ok = new JButton("登录");
  cancle = new JButton("取消");
  ok.addActionListener(new listenEvent());
  cancle.addActionListener(new listenEvent());
  
  addcomponettocontainer();
  this.setDefaultCloseOperation(EXIT_ON_CLOSE);
  
 }

 public void addcomponettocontainer()
 {
  Container c = this.getContentPane();
  c.setLayout(null);
  
  name.setBounds(10,10,100,30);
  ip.setBounds(120,10,100,30);
  ok.setBounds(230,10,70,30);
  cancle.setBounds(310,10,70,30);
  
  c.add(name);
  c.add(ip);
  c.add(ok);
  c.add(cancle);
  
  this.setVisible(true);
  this.setResizable(false);
 }
 
 public class listenEvent implements ActionListener
 {

  public void actionPerformed(ActionEvent event) {
   // TODO Auto-generated method stub
   if(event.getSource()==ok)
   {
    String n = name.getText().trim();
    String i = ip.getText().trim();
    if("".equals(n)||"".equals(i))
    {
     JOptionPane.showMessageDialog(null,"昵称、IP不能够为空!","错误",JOptionPane.OK_OPTION);
    }
    else{login(n,i);}
   }
   if(event.getSource()==cancle)
   {
    name.setText("");
    ip.setText("");
   }
  }
  
 }
 
 public void login(String name,String ip)
 {
  
   try {
    socket = new Socket(ip,7777);
    DataOutputStream out = new DataOutputStream(socket.getOutputStream());
    out.writeUTF(name);
    out.flush();//强制输出缓存中的内容
    //out.close();
    new ClientFrame(name,socket);
    destroywindow();
   } catch (UnknownHostException e) {
    JOptionPane.showMessageDialog(null,"找不到主机地址(IP错误/网络故障)!","错误",JOptionPane.OK_OPTION);
    
   } catch (IOException e) {
    
   }         
 }
 
 public void destroywindow()
 {  
  this.dispose();
 }
 
 public static void main(String[] args)
 {
  new LoginFrame();
 }
}

 

 

package client;

import java.awt.Color;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Date;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class ClientFrame extends JFrame{
 private JTextArea allmsg;
 private JTextField welcome,copyright,chatmsg;
 private JButton send;
 private JScrollPane js;
    private boolean isConnected = true;
 
 public DataOutputStream out;
 public DataInputStream in;
 
 public Socket s = null; 
 
 String nic;  /*  -- 保存用户昵称 --*/
 
 
 /**
  * 初始化客户端资源
  * 1.获取从LoginFrame传递过来的参数
  * 2.初始化界面元素
  * 3.初始化通信所需要的资源 EG:输入/输出流(DataInputStream/DataOutputStream)
  * */ 
 public ClientFrame(String name,Socket socket)
 {  
  this.setSize(310,660);
  this.setLocation(290,50);  
        this.setTitle("聊天室客户端<"+name+">");/*  -- 指定窗口的标题 --*/
        
  this.s = socket;/*  -- 接收从LoginFrame中传递过来的Socket --*/  
  
  this.nic = name+" 说: ";
  
  
  welcome = new JTextField(" < "+name+" >欢迎您来到聊天室 ",100);
  welcome.setBackground(Color.blue);  
  welcome.setEnabled(false);
  
  copyright = new JTextField("             -----  all copyright @ TOP-king  -----");
  copyright.setEnabled(false);
  
  allmsg = new JTextArea();
  allmsg.setEditable(false);
  allmsg.append("                  系统消息: 欢迎登录在线聊天室 \n");
  
  js = new JScrollPane(allmsg);//为JTextArea添加滚动条  
  
  chatmsg = new JTextField("在此输入聊天信息");
  chatmsg.addActionListener(new listen());
  
  send = new JButton("发送");
  send.addActionListener(new listen());/*  -- 添加事件监听器 --*/
  
  try {    
   out = new DataOutputStream(s.getOutputStream());   
   in = new DataInputStream(s.getInputStream());   
  } catch (IOException e) {JOptionPane.showMessageDialog(null, "系统异常","错误",JOptionPane.OK_CANCEL_OPTION);}
  
  addcomponettocontainer();

  /*  -- 当用户关闭窗口时进行相关的处理 eg:Socket Data(Input/Output)Stream 的关闭--*/
  this.addWindowListener(new WindowAdapter(){
   public void windowClosing(WindowEvent we)
   {
    sendmsg("quit&logout");/*  -- 向服务器端发送关闭信息 --*/
    isConnected = false;
    destory();/*  -- 销毁窗口资源 --*/
   }
  });
  
  new Thread(new linread()).start();/*  -- 启动读取信息线程 --*/
  
 }
 
 public void addcomponettocontainer()
 {
  Container c = this.getContentPane();
  c.setLayout(null);
  
  welcome.setBounds(75,10,150,20);  
  js.setBounds(10,50,280,500);
  chatmsg.setBounds(10,560,180,30);
  send.setBounds(220,560,70,30);
  copyright.setBounds(10,600,280,20);
  
  c.add(welcome);
  c.add(js);
  c.add(chatmsg);
  c.add(send);
  c.add(copyright); 
    
  this.setVisible(true);
  this.setResizable(false);
 }
 
 class listen implements ActionListener
 {

  public void actionPerformed(ActionEvent e) {
   // TODO Auto-generated method stub
   if(e.getSource()==send||e.getSource()==chatmsg)
   {
      String msg = chatmsg.getText().trim();
      if("".equals(msg))
      {
       JOptionPane.showMessageDialog(null,"发送信息不能为空!","错误",JOptionPane.OK_OPTION);
      }
      else
      {sendmsg((new Date()).toLocaleString()+"\n"+nic+msg+"\n");chatmsg.setText("");}
   }
  } 
 }
 
 /*  -- 向服务器端发送信息 --*/
  public void sendmsg(String m)
  {
   if(isConnected)//如果socket的输出流没关闭
   {
    try {
     out.writeUTF(m);
    } catch (IOException e) {
     JOptionPane.showMessageDialog(null,"发送信息失败!(系统异常)","错误",JOptionPane.OK_OPTION);
    }
   }
   else
   {
    JOptionPane.showMessageDialog(null,"发送信息失败!(服务器关闭/网络故障)","错误",JOptionPane.OK_OPTION);
   }
  }

  /*  -- 读取信息线程 --*/
 class linread implements Runnable
 {  
  public void run()
  {
   read();
  }
  
  public void read()
  {
    while(isConnected)
    {
     try {
      String msg = in.readUTF();
      if("SYSTEM_CLOSED".equals(msg))
      {
       JOptionPane.showMessageDialog(null,"读取消息失败(服务器关闭/网络故障)!","错误",JOptionPane.OK_OPTION);
       isConnected = false;
      }
      else
        allmsg.append(msg+"\n");      
      } catch (IOException e) {     
      }                  
    }//end while 
    JOptionPane.showMessageDialog(null,"读取消息失败(服务器关闭/网络故障)!","错误",JOptionPane.OK_OPTION);
   }//end read()
 }
 
  public void destory()
  {
   try {
    this.out.close();
    this.in.close();
    this.s.close();
   } catch (IOException e) {   
   }
   this.dispose();
  }
}

 

 

 

二、运行情况

 



 



 



 

  • 大小: 59.7 KB
  • 大小: 75.3 KB
  • 大小: 74.1 KB
分享到:
评论
1 楼 zhaoshaofang 2011-07-30  
很好···我开始学习··有用·

相关推荐

    基于MFC的UDP简易聊天室

    课程设计——简易网络聊天室。 C++基于MFC开发的UDP网络聊天室。

    简单UDP聊天室 java版

    一个简单的UDP聊天室的代码,有些功能不够完善,但是基本模型都还是出来了!

    udp聊天室源码

    udp聊天室源码

    C#UDP聊天室

    学C#网络编程时写的简单UDP聊天室,设计很垃圾,主要在学习和熟悉C#网络编程,与异步。

    vb6 udp 聊天室

    vb6 udp 聊天室 客户端列表 心跳判断在线.

    udp实现聊天室项目

    udp实现聊天室项目,有注册,登陆,群聊,私聊功能。采用sqlite3数据库保存用户信息,采用链表实现群聊和私聊功能。

    C#实现UDP简单聊天室功能(winform版)

    开发工具使用的是VS2017,基于UDP协议实现的一个简单聊天室功能,包括客户端和服务器端,首先运行服务器端,接着调试-&gt;启动新实例开启多个客户端,每开启一个客户端,服务器端会显示XXX连接等提示。客户端发送消息给...

    JAVA实现UDP聊天室完整项目

    JAVA实现UDP聊天室完整项目

    c语言实现的udp聊天室

    基于linux网络编程视频实现的UDP聊天室, 自己实现的管理用户的链表

    UDP聊天室.zip

    使用 Qt 基于 UDP 协议构建网络聊天室实例,包含 UdpServerDemo 和 UdpClientDemo 两部分程序,由于 UDP 方式不会建立连接,所以在服务端采用QList容器管理客户端状态。

    基于UDP协议的聊天室设计

    基于UDP协议的聊天室设计,我们做的课程设计,希望对大家有用

    UDP实现简单聊天室功能

    UDP实现简单聊天室功能。 用linux运行,需要修改广播地址,用tail命令打开recv.txt。

    基于UDP的聊天室编程2(客户端)

    基于UDP的聊天室编程2(客户端)--由于该程序内含两个小程序,受上传权限20M的影响,只能将两个小程序分开,此为该聊天室程序的客户端,请继续下载基于UDP的聊天室编程1(服务器端),下载完后请放在同一个文件夹中...

    java之UDP聊天室

    这是一个聊天室,实现了多对多的聊天,可以作为参考

    udp聊天报告 udp聊天报告

    udp聊天报告 udp聊天报告 udp聊天报告 udp聊天报告udp聊天报告 udp聊天报告udp聊天报告 udp聊天报告udp聊天报告 udp聊天报告

    TCP+UDP聊天室

    TCP+UDP通信聊天室,C与S之间的连接使用TCP,C与C之间的通信使用UDP通信。

    udp聊天室,java Swing可视化

    Udp聊天室,Java Swing可视化界面编写,有文字聊天和语音聊天两种模式,使用的本地网络,适用于课设等java实验中。 免费附送课程 https://blog.csdn.net/qq_34165225/article/details/109556573#comments_13823367 ...

    UDP聊天室客户端

    C++编写的聊天客户端 服务端:https://blog.csdn.net/qq_37358422/article/details/81229028

    基于C语言开发的udp 聊天室

    基于udp通信,使用C语言开发的一个简单的聊天室

    QT UDP聊天室软件

    自己在学习中开发的基于QT开发的UDP SOCKT 类的UDP聊天室支持多成员在同一局域网的聊天自动检测上下线

Global site tag (gtag.js) - Google Analytics