Java简易多用户聊天程序项目经历
2016-09-17 20:49
543 查看
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,给程序加上注释。
昨天按照丁振凡老师著述《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,给程序加上注释。
相关文章推荐
- java在线聊天项目 客户端登陆窗口LoginDialog的注册用户功能
- 极简易版专家聊天程序--JAVA练手
- java在线聊天项目1.3版设计好友列表框功能补充,因只要用户登录就发送一串新列表,导致不同客户端好友列表不同问题
- java在线聊天项目 客户端登陆窗口LoginDialog的注册用户功能 修改注册逻辑 增空用户名密码的反馈 增加showMessageDialog()提示框
- Java UDP 多用户 组播 聊天程序
- 用Java实现的简易聊天系统(J2SE初学者练手项目)
- java学习笔记: 实现简易局域网聊天程序
- 如何利用C++ Builder 5.0 Enterprise 创建用户自己的网上聊天程序
- 如何利用C++ Builder 5.0 Enterprise 创建用户自己的网上聊天程序
- Java简单聊天程序
- UDP的简易聊天程序图型多线程版 带原代码
- UDP的简易聊天程序 (未写注释和程序感想)
- Java程序练习:设计用户输入界面,获取网址采集规则
- 如何利用C++ Builder 5.0 Enterprise 创建用户自己的网上聊天程序
- 用JAVA的applet程序做出简易魔兽密保卡
- 一个类似QQ的java聊天程序
- 如何利用C++ Builder 5.0 Enterprise 创建用户自己的网上聊天程序
- 如何利用C++ Builder 5.0 Enterprise 创建用户自己的网上聊天程序
- java语音聊天程序
- 基于UDP的聊天程序-JAVA