Java简易多用户聊天程序项目经历

博主根据《Java语言实用教程》实现了一个简单的多用户聊天程序,使用Socket进行通信。在调试过程中遇到服务器显示日志延迟、只能显示第一条消息及输入事件问题。通过分析代码,将TextArea对象传递到客户端线程,解决了服务器实时显示消息的问题。目前程序有待完善,如用户设定用户名、资源释放和添加注释等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2016-9-17 20:50

        昨天按照丁振凡老师著述《Java语言实用教程(第2版)》里面的方法,利用Socket基本实现了Java简易多用户聊天程序。服务器端没有一个显示窗体,我感觉这样不方便调试。于是在服务器的main()中利用Frame和TextArea给服务器加上了一个显示窗体。目的是服务器(以下用简写为Ser)工作日志显示。但是一调试,发现第一个链接的客户端(以下简写为Cli)能实时显示,但如果立即链接第二个Cli,则第二个Cli的链接日志没有显示出来。只有在第一个Cli发送一个消息后,第二个Cli的链接日志才会和第一个Cli发送的消息一起显示出来。

        除了这个问题外,还存在着Ser只能显示收到的第一条消息(不管是哪个Cli发的),后面不论是哪个Cli的消息都显示不出来了。而且两个Cli的输入结束事件经常不能触发。另外有个小问题:TextArea对象不能在本类外设置显示内容。后来通过参数传递解决了这个问题。还有好些问题,忘记它们的具体现象就不写了。通过不断的调试,到今晚17点半时,只剩下Ser不能显示更多消息的问题。通过认真分析(前面一直试着分析,但没静下来,所以分析了一两句就分心了- _- !)Ser链接的代码(如下)

                                Socket client = server.accept();
hint = "Client-" + (clientnum + 1) + " has connected." + "\n";
System.out.println("test connect: " + hint);
input.append(hint);

DataInputStream dis = new DataInputStream(client.getInputStream());
DataOutputStream dos = new DataOutputStream(client.getOutputStream());

                                hint = "Client-" + (clientnum + 1) + " has received." + dis.readUTF() + "\n";
System.out.println("test dis: " + hint);
input.append(hint);


allclient[clientnum] = new Client(clientnum, dis, dos);
allclient[clientnum].start();
clientnum++;

结合对ServerSocket的再次理解,发现:当Cli建立链接后,该部分代码已经被阻塞了,所以不能及时显示Cli发来的消息。只有在相应的Cli线程中去更新显示才行。于是利用参数传递,将main()中的TextArea对象传递到各Cli线程中,利用TextArea的append()实现Ser窗体实时显示收到的Cli消息。

        后面又改进了一些其他显示和提示信息。完成的程序代码如下。

---------------------------------------------------------------------------------------------------- 这是服务器的类文件 ----------------------------------------------------------------------------------------------------

import java.awt.Frame;
import java.awt.Panel;
import java.awt.TextArea;
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.ServerSocket;
import java.net.Socket;


class Client extends Thread
{
int id;
TextArea clientDisplay = new TextArea(5,30);
DataOutputStream dos;
DataInputStream dis;

public Client(int id,TextArea display, DataInputStream dis, DataOutputStream dos)
{
this.id = id + 1;
clientDisplay = display;
this.dis = dis;
this.dos = dos;
}

public void run()
{
while(true)
{
try
{
String message = dis.readUTF();
SimpleTalkServer.hint = "Message from Client-" + id + " as following:\n" + message + "\n";


clientDisplay.append(SimpleTalkServer.hint);

int m = SimpleTalkServer.clientnum;

for(int i=0; i<m; i++)
{
SimpleTalkServer.allclient[i].dos.writeUTF(message);
}
}
catch(IOException e)
{}
}
}
}


public class SimpleTalkServer
{
public static Client[] allclient = new Client[20];
public static int clientnum = 0;
public static String hint = "";


public static void main(String[] args)
{
Frame show = new Frame("Server");
Panel p = new Panel();
TextArea input = new TextArea(15, 35);

try {
ServerSocket server = new ServerSocket(8888);
hint = "Server is operating.\n";


input.setText(hint);
p.add(input);
show.add(p);
show.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent w) {
try {
String message = new String("Server closed.\n");


for (int i = 0; i < clientnum; i++) {
SimpleTalkServer.allclient[i].dos.writeUTF(message);
}
server.close();
} catch (IOException e) {
}


w.getWindow().dispose();
System.exit(0);
}
});
show.setSize(300, 300);
show.setVisible(true);


while (true) {
Socket client = server.accept();
hint = "Client-" + (clientnum + 1) + " has connected." + "\n";
input.append(hint);


DataInputStream dis = new DataInputStream(client.getInputStream());
DataOutputStream dos = new DataOutputStream(client.getOutputStream());


allclient[clientnum] = new Client(clientnum, input, dis, dos);
allclient[clientnum].start();
clientnum++;
}


} catch (IOException e) {
}
}
}

-------------------------------------------------------------------------------- 这是客户端的类文件 有一个运行参数:客户端号 ------------------------------------------------------------------------------------

import java.awt.Frame;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
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;


class receiveThread extends Thread
{
DataInputStream dis;
TextArea message;

public receiveThread(DataInputStream dis, TextArea mm)
{
this.dis = dis;
message = mm;
this.start();
}

public void run()
{
for(;;)
{
try
{
String str = new String("You have received:\n" + dis.readUTF() + "\n");
message.append(str);
}
catch(IOException e)
{}
}
}
}


public class SimpleTalkClient 
{
public static void main(String[] args) throws IOException
{
Socket client = new Socket("localhost", 8888);
DataInputStream dis = new DataInputStream(client.getInputStream());
final DataOutputStream dos = new DataOutputStream(client.getOutputStream());

Frame show = new Frame("Client-" + args[0]);
Panel p = new Panel();
final TextField input = new TextField(34);
TextArea display = new TextArea(13,35);

p.add(input);
p.add(display);
show.add(p);

new receiveThread(dis, display);

input.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
try
{
String message = new String("Client-" + args[0] + ":" +input.getText());
dos.writeUTF(message);
display.append("You have send:\n" + message + "\n");
}
catch(IOException exception)
{}
}
}
);

show.addWindowListener(new WindowAdapter() 
{
public void windowClosing(WindowEvent w) 
{
try
{
dos.writeUTF("Client-" + args[0] + ":" + "closed.");
client.close();
}
catch(IOException e)
{}

w.getWindow().dispose();
System.exit(0);
}
});

show.repaint();
show.setSize(300, 300);
show.setVisible(true);
}
}

----------------------------------------------------------------------------------------------------------------  代码结束! ----------------------------------------------------------------------------------------------------

后面有时间会持续完善。待完善的问题:用户设定用户名,Cli退出后释放该Cli所占用的位置给新的Cli,给程序加上注释。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值