广州大学java实验报告三

广州大学学生实验报告

开课实验室: 

学院

计算机科学与网络工程学院

年级、专业、班

姓名

学号

实验课程名称

Java语言实验

成绩

实验项目名称

实验二十 实验报告(三)题目

指导老师

  • 实验题目

实验任务

编写一个 Java 应用程序,实现图形界面多人聊天室(多线程实现),要求聊天室窗口标题是

“欢迎使用 XXX 聊天室应用”,其中 XXX 是自己的班级姓名学号,如“软件 171 张三 1234”。

二、实验目的

熟悉 Java 综合应用程序的开发。

、程序设计

(1)程序代码:Server.java

import java.io.DataInputStream;

import java.io.DataOutputStream;

import java.io.IOException;

import java.net.ServerSocket;

import java.net.Socket;

import java.util.Collection;

import java.util.Collections;

import java.util.HashMap;

import java.util.Map;

import java.util.Set;



public class Server {

public final static Map<Socket,String> socketsMaps = Collections.synchronizedMap(new HashMap<Socket,String>()); //定义Map集合用于存储用户的Socket以及用户的名字   key:Socket    Value:用户名

public static void main(String[] args) {

// TODO Auto-generated method stub

try {

ServerSocket serverSocket = new ServerSocket(7777); // 创建服务端套接字

                          System.out.println("------多人聊天服务器已开启-------");

while (true) {

Socket socket = serverSocket.accept(); // 监听客户端套接字,若有客户端连接,则代码不会往下执行,否则会堵塞在此处。

new ThreadServer(socket).start(); // 开启线程,用于读取客户端发送的信息,并转发给每一个客户端

}

} catch (Exception e) {

e.printStackTrace(); // TODO: handle exception

}

}

}

class ThreadServer extends Thread {

private Socket socket;

ThreadServer(){};

ThreadServer(Socket socket) {

this.socket = socket;

}

@Override

public void run() {  //重写run方法

try {

while(true){

DataInputStream dis = new DataInputStream(socket.getInputStream());

String data = dis.readUTF();

if(data.startsWith("①②③④")&&data.endsWith("①②③④"))  {     //发送过来的是用户信息

Server.socketsMaps.put(socket, data.replace("①②③④",""));    //将Socket以及用户名字都存放在Map集合中

Set<Socket> sockets = Server.socketsMaps.keySet();     //获取所有的key(Socket),将所有用户的名字发送至客户端

Collection<String> names = Server.socketsMaps.values(); //获取所有的用户的名字,将这些名字拼装成一个字符串

StringBuffer sbf = new StringBuffer();

for(String userName :names) {

sbf.append(userName).append(",");

}

System.out.println("sbf:"+sbf.toString());

for(Socket soc:sockets) {

DataOutputStream dos = new DataOutputStream(soc.getOutputStream());

dos.writeUTF("①②③④"+sbf.toString()+"①②③④");

dos.flush();

}

}

else  { //发送过来的是聊天信息

Set<Socket> sockets = Server.socketsMaps.keySet(); //获取所有的key(Socket),将所有用户的名字发送至客户端

for(Socket soc:sockets)  {  //將聊天信息广播出去

DataOutputStream dos = new DataOutputStream(soc.getOutputStream());

dos.writeUTF(Server.socketsMaps.get(socket)+":"+data);

dos.flush();

}

}

}

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

(2)程序代码:Client.java

import java.awt.BorderLayout;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.io.DataInputStream;

import java.io.DataOutputStream;

import java.io.IOException;

import java.net.Socket;

import javax.swing.Box;

import javax.swing.BoxLayout;

import javax.swing.DefaultListModel;

import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JLabel;

import javax.swing.JList;

import javax.swing.JOptionPane;

import javax.swing.JPanel;

import javax.swing.JScrollPane;

import javax.swing.JTextArea;



public class Client {

private JFrame mainWin = new JFrame("聊天窗口");

private JTextArea displayTa = new JTextArea(14, 40); // 消息展示框

private DefaultListModel<String> userListModel = new DefaultListModel<>(); // 在线用户名称展示框

private JList<String> userList = new JList<>(userListModel);

private JTextArea inputTF = new JTextArea(4, 40); // 消息发送框

private JButton sendBn = new JButton("发送"); // 消息按钮

private String curUser; // 用户记录当前聊天用户名

public static void main(String[] args) {

new Client().init();

}

private void init() {

try {

String userName = JOptionPane.showInputDialog(mainWin, "请输入您的班级姓名学号:"); // 弹出“输入”对话框获取用户输入的信息

curUser = userName; // 把用户输入的信息,赋给curUser

mainWin.setTitle(curUser + "的聊天窗口");

Socket socket = new Socket("127.0.0.1", 7777);     // 创建套接字

DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); // 向服务器声明

dos.writeUTF("①②③④"+userName+"①②③④");     //发送用户名到服务端

dos.flush();

new ThreadClient(socket, this).start();     // 开启线程,用于读取服务器发送的信息

JPanel bottomPanel = new JPanel();

mainWin.add(bottomPanel, BorderLayout.SOUTH); // 将消息框和发送按钮添加到聊天窗口的底端

bottomPanel.add(inputTF);

bottomPanel.add(sendBn);

ActionListener listener = new ActionListener() {

@Override

public void actionPerformed(ActionEvent e) {

String message = inputTF.getText(); // 获取用户发送的消息

sendSms(message,socket);

}

};

sendBn.addActionListener(listener);  // 给发送消息按钮添加事件监听器

JPanel centerPanel = new JPanel();

mainWin.add(centerPanel); // 将展示消息区centerPanel添加到窗口的中间

centerPanel.add(new JScrollPane(displayTa)); // 让展示消息区可以滚动

displayTa.setEditable(false);

Box rightBox = new Box(BoxLayout.Y_AXIS); // 用户列表和是否私聊放到窗口的最右边

userList.setFixedCellWidth(60);

userList.setVisibleRowCount(13);

rightBox.add(new JLabel("在线用户列表:"));

rightBox.add(new JScrollPane(userList));

centerPanel.add(rightBox);

mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 关闭窗口退出当前程序

mainWin.pack(); // swing加上这句就可以拥有关闭窗口的功能

mainWin.setVisible(true);



} catch (Exception e) {

// TODO: handle exception

e.printStackTrace();

}

}

protected void sendSms(String sms, Socket socket) { //点击发送后将消息发送到服务器

try {

DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); //发送聊天消息到服务端

dos.writeUTF(sms);

dos.flush();



} catch (Exception e) {

// TODO: handle exception

e.printStackTrace();

}

}



public DefaultListModel<String> getUserListModel() {

return userListModel;

}



public JTextArea getDisplayTa() {

return displayTa;

}

public JTextArea getInputTF()

{

return inputTF;

}

}

class ThreadClient extends Thread {  // 继承多线程类,用来读取服务器发送的信息

private Socket socket;

private Client client;

ThreadClient() {

}

ThreadClient(Socket socket, Client client) {

this.socket = socket;

this.client = client;

}

@Override

public void run() {        //重写run方法

try {

while (true) {

DataInputStream dis = new DataInputStream(socket.getInputStream());

String message = dis.readUTF();

if(message.startsWith("①②③④")&&message.endsWith("①②③④")) //输入信息为用户名时

{

String[] names = message.replace("①②③④","").split(",");

client.getUserListModel().clear();// 清空用户列表

for (int i = 0; i < names.length; ++i) {

client.getUserListModel().addElement(names[i]);

}

}

else     //输入信息为聊天信息时,将聊天信息放在displayTa中

{

client.getInputTF().setText("");

client.getDisplayTa().append(message+"\t\n");

}

}

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

四、程序运行与测试

运行的结果如图所示。

(图片涉及个人隐私,大家可以自己在命令行窗口运行上述代码,不行的话可以在评论区留言~)

五、实验总结与心得

1、该实验是一个综合性的实验,它用到了这学期学Java的很多知识,例如:图形界面、多线程、网络编程等。以实现多人聊天的功能。

2、通过与同学的讨论与思考,摸清了这个应用的实现思路。首先需要两个类,一个叫Server,用来接受信息,并把收到的信息传到在线用户的聊天框中去。另一个叫Client,用来输入聊天内容。

3、需要特别注意的是:

(1)Server若是没有写成多线程的形式,将会给一个用户一直占用资源。

(2)用户的输入其实就是一个循环机制,用户需要的话就可以一直输入聊天内容,然后聊天内容会经过服务器传给在线用户的聊天框中,从而实现多人聊天的功能。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值