📄 chat.java
字号:
////////////////////////////////////////////////////////////////
//名称:Chat //
//功能:在网上互相传送信息 //
//作者:王越 //
//日期:2006年8月8日 //
//最后修改日期:2006年8月12日 //
///////////////////////////////////////////////////////////////
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import java.net.*;
import javax.swing.*;
public class Chat extends JFrame implements Runnable
{
//Data member
private final int RECEIVE_PORT = 8002; //接收信息的端口,运行时一直监听,不能使用系统中正在使用的端口,例如6000是QQ的端口号,也不能同时启动多个绑定到同一端口的Chat程序。
private final int SEND_PORT = 8001; //要发到对方的端口号
private final int DATA_SIZE = 100; //设置可以接收的数据包的字节数
private String IPAddress = "127.0.0.1"; //发送数据包要到的目的IP,初骀IP地址使用本地测试地址, 不能使用192.168.*.*和10.*.*.*等,因为路由器不转发这些地址
private DatagramSocket dsConnection; //UDP的连接对象
private String strEndLine = System.getProperty("line.separator"); //换行符;
private boolean isStop = false; //标志是否结束运行时一直监听接收信息端口的线程,结束时关闭UDP连接对象dsConnection
//Swing component
private JTextArea jtReceive;
private JTextArea jtSend;
private JLabel jlAdvertisement;
private JLabel jlPhoto;
private JLabel jlInformation;
private JLabel jlIPAddress;
private JTextField jtfIPAddress;
private JButton jbOK;
private JButton jbSend;
private JButton jbExit;
private JButton jbClear;
private JScrollPane jspUp;
private JScrollPane jspDown;
private JPanel jpBottom;
private JPanel jpSendRight;
private JSplitPane hMiddlePane;
private JSplitPane vUpMiddlePane;
private JSplitPane vDownMiddlePane;
//以下为成员函数
public Chat(String title)//构造函数
{
super(title);
//init JFrame
jlAdvertisement = new JLabel("Welcome!");
jlPhoto = new JLabel();
jlPhoto.setIcon(new ImageIcon("image" + File.separator + "Jupiter.gif"));
jlInformation = new JLabel();
jlInformation.setIcon(new ImageIcon("image" + File.separator + "Jupiter.gif"));
jlIPAddress = new JLabel("IP:");
jtfIPAddress = new JTextField(IPAddress);
jtfIPAddress.setHorizontalAlignment(JTextField.LEFT);
jtfIPAddress.setColumns(15);
jbOK = new JButton("OK");
jbOK.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
int option = JOptionPane.showConfirmDialog(null,"你想要将发送的的目标IP地址设为:" + jtfIPAddress.getText().trim() + "吗?","提示",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE);
if (option == JOptionPane.YES_OPTION)
{
IPAddress = jtfIPAddress.getText().trim();
}
else
{
jtfIPAddress.setText("");
}
}
});
}
});
jtReceive = new JTextArea();
jtReceive.setEditable(false);
//jtReceive.setSize(200,123);
jspUp = new JScrollPane(jtReceive);
vUpMiddlePane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, jspUp, jlPhoto);
vUpMiddlePane.setContinuousLayout(true);
vUpMiddlePane.setOneTouchExpandable(true);
vUpMiddlePane.setResizeWeight(1);
jtSend = new JTextArea();
//jtSend.setSize(300,200);
jspDown = new JScrollPane(jtSend);
jtSend.addKeyListener(new KeyAdapter()
{
public void keyTyped(KeyEvent e)
{ //发送信息框得到焦点时,按Alt+s 或者Alt+S,则发送信息
boolean isSendKey =((e.isAltDown() && e.getKeyChar()=='s') || (e.isAltDown() && e.getKeyChar()=='S'));
//发送信息框得到焦点时,按Alt+e 或者Alt+E,则退出程序
boolean isExitKey =((e.isAltDown() && e.getKeyChar()=='e') || (e.isAltDown() && e.getKeyChar()=='E'));
//发送信息框得到焦点时,按Alt+c 或者Alt+C,则清空接收信息框
boolean isClearKey =((e.isAltDown() && e.getKeyChar()=='c') || (e.isAltDown() && e.getKeyChar()=='C'));
if (isSendKey)
{
sendMessage();
}
else if (isClearKey)
{
clearReceive();
}
else if (isExitKey)
{
exitChat();
}
}
});
jbSend=new JButton("Send(s)");
jbSend.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
sendMessage();
}
});
jbClear = new JButton("Clear(c)");
jbClear.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
clearReceive();
}
});
jbExit = new JButton("Exit(e)");
jbExit.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
exitChat();
}
});
jpBottom = new JPanel();
jpBottom.setLayout(new FlowLayout());
jpBottom.add(jbSend);
jpBottom.add(jlIPAddress);
jpBottom.add(jtfIPAddress);
jpBottom.add(jbOK);
jpBottom.add(jbClear);
jpBottom.add(jbExit);
jpSendRight = new JPanel();
jpSendRight.add(jlInformation);
vDownMiddlePane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,jspDown,jpSendRight);
vDownMiddlePane.setAutoscrolls(true);
vDownMiddlePane.setContinuousLayout(true);
vDownMiddlePane.setOneTouchExpandable(true);
vDownMiddlePane.setResizeWeight(1);
hMiddlePane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, vUpMiddlePane, vDownMiddlePane);
hMiddlePane.setAutoscrolls(true);
hMiddlePane.setContinuousLayout(true);
hMiddlePane.setOneTouchExpandable(true);
hMiddlePane.setResizeWeight(1);
//hMiddlePane.setDividerSize(20);
setLayout(new BorderLayout());
getContentPane().add(jlAdvertisement,BorderLayout.NORTH);
getContentPane().add(hMiddlePane,BorderLayout.CENTER);
getContentPane().add(jpBottom,BorderLayout.SOUTH);
//还没有找到能够将关闭窗口事件停止的方法
// this.addWindowListener(new WindowAdapter()
// {
// public void windowClosing(WindowEvent e)
// {
// exitChat();
// }
// });
}
public void run() //实现Runnable接口中的run函数,启动接收信息线程
{
try
{
dsConnection=new DatagramSocket(RECEIVE_PORT);//在port 建立Socket
}
catch (Exception ex)
{
ex.printStackTrace();
}
while (!isStop) //循环等待接收信息
{
receiveMessage();
}
dsConnection.close(); //关闭DatagramSocket在port上的连接
}
private void sendMessage() //发送信息
{
try
{
final String strSendMessage = jtSend.getText().trim(); //strSendMessage不能大于DATA_SIZE设置的字节数,否则会丢失多余的信息
if (!strSendMessage.equals(new String(""))) //如果发送信息框不为空,发送信息,否则提示不能为空。
{
//DatagramPacket dp=new DatagramPacket(strSendMessage.getBytes(),strSendMessage.length(),InetAddress.getLocalHost(),SEND_PORT);//本地测试
DatagramPacket dp = new DatagramPacket(strSendMessage.getBytes(),strSendMessage.length());
//dp.setSocketAddress(new InetSocketAddress("USER-F470543094",SEND_PORT)); //通过计算机名创建 InetSocketAddress
//dp.setSocketAddress(new InetSocketAddress("59.64.68.145",SEND_PORT)); //通过IP创建 InetSocketAddress
dp.setSocketAddress(new InetSocketAddress(IPAddress,SEND_PORT));
dsConnection.send(dp);
EventQueue.invokeLater(new Runnable()
{
public void run()
{
jtReceive.append("You: " + new Date().toString() + strEndLine);
jtReceive.append(" " + strSendMessage + strEndLine);
jtSend.setText("");
}
});
}
else
{
JOptionPane.showMessageDialog(null,"不能发送空的信息 !","提示",2);
}
}
catch (NullPointerException ex)
{
JOptionPane.showMessageDialog(null,"IP地址可能不正确,请重新输入 !","提示",2);
}
catch (NoRouteToHostException ex)
{
JOptionPane.showMessageDialog(null,"对方可能不在线,不能向不在线的人发送信息 !","提示",2);
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
private void receiveMessage() //收信息线程
{
try
{
final byte[] buf = new byte[DATA_SIZE];
final DatagramPacket dp = new DatagramPacket(buf,DATA_SIZE);
dsConnection.receive(dp);
if (dp != null)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
jtReceive.append("(" + dp.getAddress().toString() + ") " + new Date().toString() + strEndLine); //或者使用new Date().toLocaleString()
jtReceive.append(" " + new String(buf,0,dp.getLength()) + strEndLine);
}
});
}
}
catch (NullPointerException ex)
{
JOptionPane.showMessageDialog(null,"发生了系统端口错误,程序即将退出 !","提示",JOptionPane.ERROR_MESSAGE);
System.exit(0);
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
private void clearReceive() //清空接收信息框
{
int option = JOptionPane.showConfirmDialog(null,"你相要将接收信息框清空吗?","提示",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE);
if (option == JOptionPane.YES_OPTION)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
jtReceive.setText("");
}
});
}
}
private void exitChat() //退出Chat程序
{
int option = JOptionPane.showConfirmDialog(null,"你想要退出吗?","提示",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE);
if (option == JOptionPane.YES_OPTION)
{
isStop = true; //先停止接收线程
try
{
new Thread().sleep(100); //暂停0.1秒后退出程序,以保证有时间停止接收线程,关闭DatagramSocket的连接对象
System.exit(0); //结束程序
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
public static void main(String[] args) //单元测试的主函数
{
Chat jfChat =new Chat("Chat");
jfChat.setSize(600,400);
jfChat.setLocation(300,200);
jfChat.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jfChat.setVisible(true);
new Thread(jfChat).start(); //启动接收信息线程
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -