📄 client.java
字号:
//Client.java
//作者:毛伟,贾桂卿,郭威
//基于TCP的聊天软件客户端
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.lang.*;
/*=============================================================
描述:实现客户端界面
创建连接线程,向用户指定的运行服务器端软件的主机发出连接请求
创建接收线程,接收服务器端发来的数据
创建发送线程,向服务器端发送数据
==============================================================*/
public class Client extends JFrame
{
private JTextField tField = new JTextField("输入");
private JTextField ipAddress = new JTextField("输入服务器地址");
private JTextArea tArea = new JTextArea("聊天记录:", 40, 20);
private JScrollPane scrollArea = new JScrollPane(tArea,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
private JPanel buttons=new JPanel();
private JButton connect = new JButton("连接");
private JButton send = new JButton("发送");
private JButton clear = new JButton("清除");
private JButton quit = new JButton("退出");
private Socket connectionSocket;
private String chatServer;
Object sendObj=new Object();
Object connectObj=new Object();
Thread waitSend;
Thread waitRcv;
Thread waitConnect;
/*===============================================
描述:Client类的构造函数,用来创建客户端界面
================================================*/
public Client(String title)
{
super(title);
Container cp = getContentPane();
ButtonHandler handler = new ButtonHandler();
tField.addActionListener(handler);
ipAddress.addActionListener(handler);
connect.addActionListener(handler);
send.addActionListener(handler);
clear.addActionListener(handler);
quit.addActionListener(handler);
BorderLayout layout=new BorderLayout();
cp.setLayout(layout);
cp.add(BorderLayout.WEST,scrollArea);
cp.add(BorderLayout.SOUTH,tField);
tField.setEnabled(false);
cp.add(BorderLayout.CENTER,buttons);
FlowLayout layout1 = new FlowLayout();
buttons.setLayout(layout1);
buttons.add(ipAddress);
buttons.add(connect);
buttons.add(send);
send.setEnabled(false);
buttons.add(clear);
clear.setEnabled(false);
buttons.add(quit);
quit.setEnabled(false);
setSize(340, 218);
setVisible(true);
}
/*===============================================
描述:启动连接线程,请求服务器端连接
================================================*/
public void runClient()
{
waitConnect = new Thread(new ConnectThread());
waitConnect.start();
}
/*===============================================
描述:启动客户端接收和发送线程
================================================*/
public void InitilaSendRcvThread()
{
ipAddress.setEnabled(false);
connect.setEnabled(false);
tField.setEnabled(true);
send.setEnabled(true);
clear.setEnabled(true);
quit.setEnabled(true);
waitSend = new Thread(new SendThread());
waitSend.start();
waitRcv = new Thread(new RcvThread());
waitRcv.start();
}
/*===============================================
描述:连接线程类,向服务器端发出连接请求
用内部类实现
================================================*/
private class ConnectThread implements Runnable
{
public ConnectThread()
{
}
public void run()
{
synchronized(connectObj)
{
try
{
connectObj.wait();
tArea.append("\n正在连接>>>>>>");
connectionSocket = new Socket(InetAddress.getByName(chatServer),8080);
tArea.append("\n已连接到:"+connectionSocket.getInetAddress().getHostName());
InitilaSendRcvThread();
}
catch(InterruptedException e)
{
}
catch(EOFException eo)
{
tArea.append("\n服务端终止连接!");
}
catch(IOException io)
{
io.printStackTrace();
tArea.append("\n连接服务器失败!\n请退出,重新启动客户端!");
}
}
}
}
/*===============================================
描述:Client类的入口点函数,也是整个客户端的入口点
================================================*/
public static void main(String[] args)
{
Client frame1=new Client("客户端");
frame1.addWindowListener(new WindowClose());
frame1.runClient();
}
/*===============================================
描述:清除函数,在客户端退出与服务器端通信时,
终止各类线程,关闭建立的套接字连接。
================================================*/
public void cleanAll() throws IOException
{
if(waitRcv != null)
{
waitRcv.stop();
waitRcv=null;
}
if(waitSend != null)
{
waitSend.stop();
waitSend=null;
}
if(waitConnect != null)
{
waitConnect.stop();
waitConnect=null;
}
if(connectionSocket != null)
{
connectionSocket.close();
connectionSocket=null;
}
}
/*===============================================
描述:发送线程类,向服务器端发送用户需要传递的数据
用内部类实现
================================================*/
private class SendThread implements Runnable
{
ObjectOutputStream output;
public SendThread()
{
try
{
output=new ObjectOutputStream(connectionSocket.getOutputStream());
output.flush();
}
catch(IOException iException)
{
iException.printStackTrace();
tArea.append("\n初始化输出失败!");
}
}
public void run()
{
while(true)
{
synchronized(sendObj)
{
try
{
sendObj.wait(0);
output.writeObject(tField.getText());
}
catch(InterruptedException e)
{
}
catch(IOException io)
{
}
}
}
}
}
/*===============================================
描述:接收线程类,接收来自服务器端传来的数据
用内部类实现
================================================*/
private class RcvThread implements Runnable
{
ObjectInputStream input;
public RcvThread()
{
try
{
input = new ObjectInputStream(connectionSocket.getInputStream());
}
catch(IOException iException)
{
tArea.append("\n初始化输入失败!");
}
}
public void run()
{
while(true)
{
try
{
String str = (String)input.readObject();
tArea.append("\n服务器>>"+str);
tArea.setCaretPosition(tArea.getText().length());
}
catch(ClassNotFoundException e)
{
tArea.append("\n未知格式的数据包!");
}
catch(IOException io)
{
}
}
}
}
/*===============================================
描述:事件监听函数,监测并处理用户操作时引发的事件。
================================================*/
private class ButtonHandler implements ActionListener
{
public void actionPerformed (ActionEvent e)
{
if(e.getSource() == ipAddress)
{
chatServer = e.getActionCommand();
synchronized(connectObj)
{
connectObj.notify();
}
}
else if(e.getSource() == connect)
{
chatServer = ipAddress.getText();
synchronized(connectObj)
{
connectObj.notify();
}
}
else if(e.getSource() == tField)
{
sendData(e.getActionCommand());
synchronized(sendObj)
{
sendObj.notify();
}
}
else if(e.getSource() == send)
{
sendData(tField.getText());
synchronized(sendObj)
{
sendObj.notify();
}
}
else if(e.getSource() == clear)
{
tArea.setText("聊天记录:");
tField.setText("");
}
else if(e.getSource() == quit)
{
try
{
cleanAll();
System.exit(0);
}
catch (IOException io)
{
tArea.append("\n关闭通信端口失败!");
}
}
}
}
public void sendData(String message)
{
tArea.append("\n客户端>>"+message);
}
}
/*===============================================
描述:用户关闭客户端界面的事件处理类
================================================*/
class WindowClose extends WindowAdapter
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -