您的位置:首页 > 编程语言 > Java开发

基于java实现的UDP多用户聊天应用

2014-01-10 12:20 453 查看
第一次写博客,还请大家多多指教

因为最近做了一个关于计算机网络的课程设计,是一个多用户聊天软件,实现过程比较简单,现在就拿来和大家分享一下,如果程序有什么不正确的地方希望大家多多提点意见

谢谢大家

以下是具体实现的程序代码

客户端程序:

1.用户运行的第一个界面,用于设置用户名

Setusername.java

package zhonghui.client;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class Setusername extends JFrame{

private JButton jbt = new JButton("进入聊天室");
private JTextField jtfname= new JTextField(8);

public static void main(String[] args) {

new Setusername();
}
public Setusername(){
final JPanel p1 = new JPanel();
p1.setLayout(new BorderLayout());
p1.add(new JLabel("输入用户名"), BorderLayout.WEST);
p1.add(jtfname, BorderLayout.CENTER);
jtfname.setHorizontalAlignment(JTextField.LEFT);
p1.add(jbt, BorderLayout.EAST);
p1.setLayout(new FlowLayout(FlowLayout.LEFT,10,20));
p1.setSize(300, 100);
setLayout(new BorderLayout());
add(p1, BorderLayout.CENTER);
add(new JLabel("欢迎使用多人聊天系统  ,请输入用户名即可进入聊天室  "), BorderLayout.NORTH);
setTitle("多人聊天室 ");
setSize(350, 150);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);

jbt.addActionListener(new ActionListener() {

@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
String username = jtfname.getText().trim();
if(username.equals("")){
}else{
//关闭设置页面,启动聊天框页面
setVisible(false);
new Client(username);
}
}
}); // Register listener
}
}
2.用户使用的聊天界面类,实现与服务器通信,本客户端连接的IP是127.0.0.1,即只要服务器在本地运行,即可进行通信

Client.java

package zhonghui.client;

import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.border.TitledBorder;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

public class Client extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;

// 接受消息框
private JTextField jtf = new JTextField();

private String username=null;

// 显示信息框
private JTextArea jta = new JTextArea();
private JTextArea userlist = new JTextArea(10,10);

// IO
private DataOutputStream toServer;
private DataInputStream fromServer;

public Client(String username) {

this.username=username;
//设置输入框
final JPanel p = new JPanel();
p.setLayout(new BorderLayout());
p.add(new JLabel("输入聊天内容(回车发送)"), BorderLayout.WEST);
p.add(jtf, BorderLayout.CENTER);
jtf.setHorizontalAlignment(JTextField.LEFT);
add(p, BorderLayout.SOUTH);
//在版面的中间增加一个聊天信息显示框
add(new JScrollPane(jta), BorderLayout.CENTER);
jta.setEditable(false);
//设置用户列表
final JPanel p2 = new JPanel();
p2.setLayout(new BorderLayout());
p2.setBorder(new TitledBorder("用户列表"));
p2.add(new JScrollPane(userlist), BorderLayout.CENTER);
userlist.setEditable(false);
add(p2, BorderLayout.EAST);
jtf.addActionListener(new ButtonListener()); // Register listener
setTitle("多人聊天室欢迎你:"+username);
setSize(500, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);

JSONObject data =new JSONObject();
data.put("username", username);
data.put("msg", null);

try {
//创建一个socket链接服务器
Socket socket = new Socket("127.0.0.1",8000);

// 创建一个输入流用于获取服务器的数据
fromServer = new DataInputStream(
socket.getInputStream());

// 创建一个输出流用于向服务器发送数据
toServer =
new DataOutputStream(socket.getOutputStream());
//向服务器发送数据(用户名)
toServer.writeUTF(data.toString());
//开启一个线程,用于读取服务器发送过来的数据
ReadThread readThread = new ReadThread();
readThread.start();

}
catch (IOException ex) {
jta.append("服务器无响应");
}
}

private class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
try {
// 设置日期格式
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 设置日期格式
String time =df.format(new Date()).toString();
//获取输入框信息
String msg = jtf.getText().trim();
if(msg.equals("")){}else{
//打包数据成json格式
JSONObject data =new JSONObject();
data.put("username", username);
data.put("msg", msg);
data.put("time",time);
//向服务器发送数据
toServer.writeUTF(data.toString());
jtf.setText("");
}
}
catch (Exception ex) {
System.err.println(ex);
}
}
}
public class ReadThread extends Thread {

public void run() {
String json = null;
try {
//无线循环监听服务器发来的数据
while (true) {
//读取服务器的数据
json = fromServer.readUTF();
//转化成json格式
JSONObject data = JSONObject.fromObject(json.toString());
if(json != null){
//打印聊天信息或者系统提示信息
jta.append( data.getString("msg") + "\n");
//强制使光标移动最底部
jta.selectAll();
//刷新用户列表
String list = "";
JSONArray jsonArray = data.getJSONArray("userlist");
for(int i=0;i<jsonArray.size();i++){
list=list+jsonArray.get(i)+"\n";
}
userlist.setText(list);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

}


服务器端:

1.一个User类用于保存用户的信息

User.java

package zhonghui.server;

import java.net.Socket;

public class User {

private String UserName="";
private Socket socket;

public String getUserName() {
return UserName;
}
public void setUserName(String userName) {
UserName = userName;
}
public Socket getSocket() {
return socket;
}
public void setSocket(Socket socket) {
this.socket = socket;
}

}


2.服务器实现的类,采用多线程,实现与多个客户端通信,同时转发一个用户的信息给所有的在线用户

MultiThreadServer.java

package zhonghui.server;

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

import net.sf.json.JSONObject;

public class MultiThreadServer extends JFrame {

private static final long serialVersionUID = 1L;
// 服务器启动的时候新建一个聊天组
//这是一个用户信息列表
ArrayList<User> clientList = new ArrayList<User>();
//这是在线用户名列表
ArrayList<String> usernamelist = new ArrayList<String>();
//创建一个信息显示框

4000
private JTextArea jta = new JTextArea();
//声明一个用户对象,该类里面有两个变量 socket,username;
private User user = null;
//声明一个输出流
DataOutputStream output = null;
//声明一个输入流
DataInputStream input = null;

public static void main(String[] args) {
new MultiThreadServer();
}

public MultiThreadServer() {
// 设置信息显示框版面
setLayout(new BorderLayout());
add(new JScrollPane(jta), BorderLayout.CENTER);
jta.setEditable(false);
setTitle("多人聊天服务器 ");
setSize(500,300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true); //

try {
// 创建一个服务器socket,绑定端口8000
ServerSocket serverSocket = new ServerSocket(8000);
//打印启动时间
jta.append("服务器启动时间 " + new Date() + '\n');
//无限循环监听是否有新的客户端连接
while (true) {
// 监听一个新的连接
Socket socket = serverSocket.accept();
if(socket!=null){
//获取上线用户的信息
input = new DataInputStream(
socket.getInputStream());
String json = input.readUTF();
JSONObject data = JSONObject.fromObject(json.toString());
jta.append("用户:" + data.getString("username") +
"在" + new Date()+"登陆系统" + '\n');
//显示用户登录ip地址
InetAddress inetAddress = socket.getInetAddress();
jta.append("用户" + data.getString("username") + "的IP地址是:"
+ inetAddress.getHostAddress() + "\n");
//新建一个用户对象
user = new User();
//设置该用户对象的socket
user.setSocket(socket);
//设置用户名
user.setUserName(data.getString("username"));
//加入在线用户组列表
clientList.add(user);
//加入用户名列表(用户显示在客户端的用户列表)
usernamelist.add(data.getString("username"));
}
//用户上线提示,打包成json格式数据
JSONObject online = new JSONObject();
online.put("userlist", usernamelist);
online.put("msg", user.getUserName()+"上线了");

//提示所有用户有新的用户上线
for (int i = 0; i < clientList.size(); i++) {
try{
User otheruser = clientList.get(i);
//获取每一个用户的socket,得到输出流,
output = new DataOutputStream(otheruser.getSocket().getOutputStream());
//向每个用户端发送数据
output.writeUTF(online.toString());
}catch(IOException ex){
System.err.println(ex);
}
}
//新开一个线程,并将当前连接用户的socket传给这个线程,该线程用于负责监听该socket的数据
HandleAClient task = new HandleAClient(socket);
new Thread(task).start();

}
}catch(IOException ex) {
System.err.println(ex);
}
}

// 线程类
class HandleAClient implements Runnable {
private Socket socket; //已连接的cocket

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

public void run() {

try {
// 获取本线程监听的socket客户端的输入流
DataInputStream inputFromClient = new DataInputStream(
socket.getInputStream());

// 循环监听
while (true) {
// 获取客户端的数据
String json = inputFromClient.readUTF();

JSONObject data = JSONObject.fromObject(json.toString());
//将获取的数据转发给每一个用户
for (int i = 0; i < clientList.size(); ) {
try{
//将聊天的信息和用户列表打包成json格式数据发给每个客户端
JSONObject chat = new JSONObject();
chat.put("userlist", usernamelist);
chat.put("msg", data.getString("username")+" "+data.getString("time")+":\n"+data.getString("msg"));
User otheruser = clientList.get(i);
output = new DataOutputStream(otheruser.getSocket().getOutputStream());
output.writeUTF(chat.toString());
i++;
}catch(IOException ex){
//如果出现异常,表明当前循环的客户端下线了
//从列表中移除
User outuser = clientList.get(i);
clientList.remove(i);
//提示每个用户有用户下线了
usernamelist.remove(outuser.getUserName());
JSONObject out = new JSONObject();
out.put("userlist", usernamelist);
out.put("msg", outuser.getUserName()+"下线了\n");
//通知下线
for (int j = 0; j < clientList.size(); j++) {
try{
User otheruser = clientList.get(j);
output = new DataOutputStream(otheruser.getSocket().getOutputStream());
output.writeUTF(out.toString());
}catch(IOException ex1){
}
}
}
}
}
}
catch(IOException e) {
System.err.println(e);
}
}
}
}


注:要能正常运行程序还需要导入支持json的包

源程序下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java udp 多线程 聊天