简单的java聊天程序

天边的云 2011-08-26 05:30:30
小弟刚学完java基础,练练手就做了一个特别简单的聊天程序,源代码如下:
import java.net.*;
import java.awt.*;
import java.awt.event.*;
public class Receive {
Frame f=new Frame("聊天室");
TextField tfIP=new TextField(15);
TextArea lst=new TextArea();
Label lb=new Label("IP");
DatagramSocket ds;
TextField tfData=new TextField(20);
Button bt=new Button("send");
Button bt2=new Button("Content can't for empty");//定义模态显示
Dialog dlg=new Dialog(f,"消息提示",true);



public static void main(String args[]){

new Receive();//调用构造函数初始化
}



public Receive(){
try{
ds=new DatagramSocket(8087);
}catch(Exception ex){
ex.printStackTrace();
}

//设置线程监听对方发送的内容
new Thread(new Runnable(){
public void run(){

byte buf[]=new byte[1024];
DatagramPacket dp=new DatagramPacket(buf,1024);
while(true){
try{
ds.receive(dp);
lst.append("对方(来自"+dp.getAddress().getHostAddress()+",接口:"+dp.getPort()+") "+"当前时间:"+"\n"+new String(buf,0,dp.getLength())+"\n");
}catch(Exception e){
e.printStackTrace();
}
}
}
}).start();
init1();
}


public void init1(){
f.setSize(400,400);//设置容器的大小
f.add(lst);
//添加组件,布置布局
Panel p1=new Panel();
Panel p2=new Panel();
Panel p3=new Panel();
p1.setLayout(new BorderLayout());
p2.setLayout(new BorderLayout());
p3.setLayout(new BorderLayout());
p1.add("West",lb);
p1.add("East",tfIP);
p2.add("West",bt);
p2.add("East",tfData);
p3.add("West",p1);
p3.add("East",p2);
f.add("South",p3);

dlg.setLayout(new FlowLayout());
dlg.add(bt2);
dlg.setBounds(0, 0, 200, 150);//设置提示框的大小

f.setVisible(true);//让容器可显示
f.setResizable(false);//不可改变容器大小

//关闭窗口事件
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
ds.close();
f.setVisible(false);
f.dispose();
System.exit(0);
}
});
//触发按钮事件
bt.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ex){
byte[]buf;
buf=tfData.getText().getBytes();
if(buf.length!=0){
try{
DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName(tfIP.getText()),8088);
ds.send(dp);
tfData.setText("");
lst.append("自己:"+"\n"+new String(buf)+"\n");//new String(dp.getData());
}catch(Exception e){
e.printStackTrace();
}
}else{//设置成为模态显示并其可现
dlg.setModal(true);
dlg.setVisible(true);
}
}
});
//模态显示按钮的触发事件
bt2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
dlg.dispose();
}
});
//输入文本框的触发事件
tfData.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){

byte[]buf;
buf=e.getActionCommand().getBytes();
if(buf.length!=0){
try{
DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName(tfIP.getText()),8088);
ds.send(dp);
((TextField)e.getSource()).setText("");
lst.append("自己:"+"\n"+new String(buf)+"\n");//new String(dp.getData());
}catch(Exception ex){
ex.printStackTrace();
}
}else{
dlg.setModal(true);
dlg.setVisible(true);
}
}
});
}
}

把上面的代码在复制一个,改变一下端口,就可以实现简单的聊天了,但还有一些功能没有实现,还请各位大虾指点一二。
未能实现的功能:双方发送的内容所显示的动态时间;发送框在程序刚开始运行的时候,光标没在发送框;发送按钮不能显示中文,不知道怎么解决这个中文乱码
还请大家帮忙啊!
...全文
2401 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
softneo 2014-04-03
  • 打赏
  • 举报
回复
真迷惑人。。。
softneo 2014-04-03
  • 打赏
  • 举报
回复
怎么用啊,擦,只能发不能收!
鱼肉烧 2013-08-16
  • 打赏
  • 举报
回复
搞错了,应该是192行,第192行那里,如果发送信息为空,则弹出“无效信息”,但是直接return的话,就没有关闭发送资源,端口还在占用着,之后发信息就会出现“本地发送端口已被使用”。所以应该在192行后面加上ds.close()
鱼肉烧 2013-08-16
  • 打赏
  • 举报
回复
楼主,我发现了一点问题,第186行那里,如果发送信息为空,则弹出“无效信息”,但是直接return的话,就没有关闭发送资源,端口还在占用着,之后发信息就会出现“本地发送端口已被使用”。所以应该在186行后面加上ds.close()
风尘中国 2011-08-27
  • 打赏
  • 举报
回复
感谢楼主和楼上哥们的代码,不过楼上是用AWT做的,我改成SWING实现,能够避免AWT带来的中文乱码问题
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.regex.Pattern;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class PointToPointUDPChat {
JFrame f = new JFrame("聊天室");

JLabel lbRemoteIP = new JLabel("目标IP");// 对方IP
JLabel lbRemotePort = new JLabel("目标端口");
JLabel lbLocalSendPort = new JLabel("本地发送端口");
JLabel lbLocalReceivePort = new JLabel("本地接收端口");

JTextField tfRemoteIP = new JTextField(15);// 要发送数据的目标IP
JTextField tfRemotePort = new JTextField(15);// 要发送数据的目标端口
JTextField tfLocalSendPort = new JTextField(15);// 使用此端口发送数据
JTextField tfLocalReceivePort = new JTextField(15);// 使用此端口发送数据

String remoteIP = null;
int remotePort = 0;
int localSendPort = 0;
int localReceivePort = 0;
JTextArea allChatContent = new JTextArea();

JTextField sendChatContent = new JTextField(20);

JButton connect = new JButton("连接");
JButton disConnect = new JButton("断开");
JButton bt = new JButton("发送");
Thread receiveThread = null;//利用start和stop控制是否接收消息

public PointToPointUDPChat() {
initFrame();
}

public static void main(String args[]) {
new PointToPointUDPChat();
}

// 外观布局,添加事件响应
public void initFrame() {// //////

f.setSize(400, 500);// 设置容器的大小
f.setLayout(new BorderLayout());
JPanel p = new JPanel();
JPanel p2 = new JPanel();

// 添加组件,布置布局
p.setLayout(new GridLayout(5, 5));
p.add(lbRemoteIP);
p.add(tfRemoteIP);
p.add(lbRemotePort);
p.add(tfRemotePort);
p.add(lbLocalSendPort);
p.add(tfLocalSendPort);
p.add(lbLocalReceivePort);
p.add(tfLocalReceivePort);
p.add(connect);
p.add(disConnect);

f.add("North", p);
connect.addActionListener(new ActionListener() {//连接按钮事件
public void actionPerformed(ActionEvent e) {
try{
remoteIP = tfRemoteIP.getText();
remotePort = Integer.parseInt(tfRemotePort.getText());
localSendPort = Integer.parseInt(tfLocalSendPort
.getText());
localReceivePort = Integer.parseInt(tfLocalReceivePort
.getText());
}catch (Exception exception) {
prompt("连接信息不能为空或格式错误");
return;
}
if (!checkIP(remoteIP)) {
prompt("目标IP设置错误");
return;
}
if (!checkPort(remotePort)) {
prompt("目标端口设置错误");
return;
}
if (!checkPort(localSendPort)) {
prompt("本地发送端口设置错误");
return;
}
if (!checkPort(localReceivePort)) {
prompt("本地接收端口设置错误");
return;
}
prompt("连接成功");
tfRemoteIP.setEditable(false);
tfRemotePort.setEditable(false);
tfLocalReceivePort.setEditable(false);
tfLocalSendPort.setEditable(false);
receiveMessage();
}
});

disConnect.addActionListener(new ActionListener() {//断开按钮事件
public void actionPerformed(ActionEvent e) {
tfRemoteIP.setEditable(true);
tfRemotePort.setEditable(true);
tfLocalReceivePort.setEditable(true);
tfLocalSendPort.setEditable(true);
tfLocalReceivePort.setText("");
tfLocalSendPort.setText("");
tfRemoteIP.setText("");
tfRemotePort.setText("");

remoteIP = null;
remotePort = 0;
localSendPort = 0;
localReceivePort = 0;
receiveThread.stop();
prompt("断开成功");
}
});

f.add("Center", allChatContent);

p2.setLayout(new FlowLayout());
p2.add(bt);
p2.add(sendChatContent);// ///p2面板添加发送按钮和要发送的内容
f.add("South", p2);

f.setLocationRelativeTo(null);//设置居中
f.setVisible(true);// 让容器可显示
f.setResizable(false);// 不可改变容器大小

// 关闭窗口事件
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
f.setVisible(false);
f.dispose();
System.exit(0);
}
});

// //////触发发送按钮事件
bt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sendMessage();
}

});
// 模态显示按钮的触发事件

// 输入文本框的触发事件
sendChatContent.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sendMessage();
}
});



}

// 发送数据
public void sendMessage() {//
//定义ds
DatagramSocket ds = null;
try {
ds = new DatagramSocket(localSendPort);
} catch (SocketException e1) {
prompt("本地发送端口已被使用");
return;
}
//设置发送信息
String sendMessage = sendChatContent.getText().trim();
if (sendMessage.equals("")) {
prompt("无效信息");
return;
}
byte[] buf = sendMessage.getBytes();// /////获得要发送的数据

//设置接收数据的远程IP地址
InetAddress inetAddress = null;
try {
inetAddress = InetAddress.getByName(tfRemoteIP.getText().trim());
} catch (UnknownHostException e) {
prompt("非法远程IP地址");
return;
}

//发送
DatagramPacket dp = new DatagramPacket(buf, 0, buf.length, inetAddress,
remotePort);
try {
ds.send(dp);
} catch (IOException e) {
prompt("网络故障,发送失败");
return;
}
sendChatContent.setText("");// //发送完数据,发送框重置为空

allChatContent.append(new java.text.SimpleDateFormat(
"yy-MM-dd HH:mm:ss").format(new Date())
+ " send to Remote("
+ dp.getAddress()
+ " "
+ dp.getPort()
+ ") :\n");
allChatContent.append(sendMessage + "\n");
ds.close();
}

// 接收数据
class MyRunnable implements Runnable {
byte buf[] = new byte[1024];
DatagramSocket ds = null;
DatagramPacket dp = null;

public void run() {
dp = new DatagramPacket(buf, 0, 1024);
try {
ds = new DatagramSocket(localReceivePort);
} catch (SocketException e1) {
prompt("本地接收端口已被使用");
return;
}
while (true) {
try {
ds.receive(dp);
} catch (IOException e) {
ds.close();
e.printStackTrace();
}
String receiveMessage = new String(dp.getData(), 0, dp
.getLength());
allChatContent.append(new java.text.SimpleDateFormat(
"yy-MM-dd HH:mm:ss").format(new Date())//
+ " from remote("
+ dp.getAddress().getHostAddress()
+ " " + dp.getPort() + ") :\n" + receiveMessage + "\n");
sendChatContent.setCaretPosition(sendChatContent.getText()
.length());

}
}

}

public void receiveMessage() {//
receiveThread = new Thread(new MyRunnable());
receiveThread.start();
}

//异常处理
public void prompt(String promptMessage) {
JOptionPane.showConfirmDialog(null, promptMessage, "友情提示",
JOptionPane.WARNING_MESSAGE);
}

public boolean checkPort(int port) {
return String.valueOf(port).matches("\\d+") && port > 1024
&& port <= 65535;

}

public boolean checkPort(String port) {
return port.matches("\\d+") && Integer.parseInt(port) > 1024
&& Integer.parseInt(port) <= 65535;

}

public boolean checkIP(String ip) {
java.util.regex.Matcher m = Pattern.compile(
"(\\d{1,3}).(\\d{1,3}).(\\d{1,3}).(\\d{1,3})").matcher(ip);
if (m.find()) {
for (int i = 1; i <= 4; i++)
if (Integer.parseInt(m.group(i)) < 0
|| Integer.parseInt(m.group(i)) > 255)
return false;
return true;
}
return true;
}

}
天边的云 2011-08-27
  • 打赏
  • 举报
回复
谢谢大家伙的帮助了
打油的程序员 2011-08-27
  • 打赏
  • 举报
回复
打油的程序员 2011-08-27
  • 打赏
  • 举报
回复
测试结果:
http://hi.csdn.net/attachment/201108/26/5180698_131438555672JC.jpg

原来.bmp图片上传不到空间,除了改后缀名,还有什么办法?
打油的程序员 2011-08-27
  • 打赏
  • 举报
回复
稍微修改了一下


import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Label;
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.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Date;
import java.util.regex.Pattern;

import javax.swing.JOptionPane;

public class PointToPointUDPChat {
Frame f = new Frame("聊天室");

Label lbRemoteIP = new Label("目标IP");// 对方IP
Label lbRemotePort = new Label("目标端口");
Label lbLocalSendPort = new Label("本地发送端口");
Label lbLocalReceivePort = new Label("本地接收端口");

TextField tfRemoteIP = new TextField(15);// 要发送数据的目标IP
TextField tfRemotePort = new TextField(15);// 要发送数据的目标端口
TextField tfLocalSendPort = new TextField(15);// 使用此端口发送数据
TextField tfLocalReceivePort = new TextField(15);// 使用此端口发送数据

String remoteIP = null;
int remotePort = 0;
int localSendPort = 0;
int localReceivePort = 0;
TextArea allChatContent = new TextArea();

TextField sendChatContent = new TextField(20);

Button connect = new Button("连接");
Button disConnect = new Button("断开");
Button bt = new Button("发送");
Thread receiveThread = null;//利用start和stop控制是否接收消息

public PointToPointUDPChat() {
initFrame();
}

public static void main(String args[]) {
new PointToPointUDPChat();
}

// 外观布局,添加事件响应
public void initFrame() {// //////

f.setSize(400, 500);// 设置容器的大小
f.setLayout(new BorderLayout());
Panel p = new Panel();
Panel p2 = new Panel();

// 添加组件,布置布局
p.setLayout(new GridLayout(5, 5));
p.add(lbRemoteIP);
p.add(tfRemoteIP);
p.add(lbRemotePort);
p.add(tfRemotePort);
p.add(lbLocalSendPort);
p.add(tfLocalSendPort);
p.add(lbLocalReceivePort);
p.add(tfLocalReceivePort);
p.add(connect);
p.add(disConnect);

f.add("North", p);
connect.addActionListener(new ActionListener() {//连接按钮事件
public void actionPerformed(ActionEvent e) {
try{
remoteIP = tfRemoteIP.getText();
remotePort = Integer.parseInt(tfRemotePort.getText());
localSendPort = Integer.parseInt(tfLocalSendPort
.getText());
localReceivePort = Integer.parseInt(tfLocalReceivePort
.getText());
}catch (Exception exception) {
prompt("连接信息不能为空或格式错误");
return;
}
if (!checkIP(remoteIP)) {
prompt("目标IP设置错误");
return;
}
if (!checkPort(remotePort)) {
prompt("目标端口设置错误");
return;
}
if (!checkPort(localSendPort)) {
prompt("本地发送端口设置错误");
return;
}
if (!checkPort(localReceivePort)) {
prompt("本地接收端口设置错误");
return;
}
prompt("连接成功");
tfRemoteIP.setEditable(false);
tfRemotePort.setEditable(false);
tfLocalReceivePort.setEditable(false);
tfLocalSendPort.setEditable(false);
receiveMessage();
}
});

disConnect.addActionListener(new ActionListener() {//断开按钮事件
public void actionPerformed(ActionEvent e) {
tfRemoteIP.setEditable(true);
tfRemotePort.setEditable(true);
tfLocalReceivePort.setEditable(true);
tfLocalSendPort.setEditable(true);
tfLocalReceivePort.setText("");
tfLocalSendPort.setText("");
tfRemoteIP.setText("");
tfRemotePort.setText("");

remoteIP = null;
remotePort = 0;
localSendPort = 0;
localReceivePort = 0;
receiveThread.stop();
prompt("断开成功");
}
});

f.add("Center", allChatContent);

p2.setLayout(new FlowLayout());
p2.add(bt);
p2.add(sendChatContent);// ///p2面板添加发送按钮和要发送的内容
f.add("South", p2);

f.setVisible(true);// 让容器可显示
f.setResizable(false);// 不可改变容器大小

// 关闭窗口事件
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
f.setVisible(false);
f.dispose();
System.exit(0);
}
});

// //////触发发送按钮事件
bt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sendMessage();
}

});
// 模态显示按钮的触发事件

// 输入文本框的触发事件
sendChatContent.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sendMessage();
}
});



}

// 发送数据
public void sendMessage() {//
//定义ds
DatagramSocket ds = null;
try {
ds = new DatagramSocket(localSendPort);
} catch (SocketException e1) {
prompt("本地发送端口已被使用");
return;
}
//设置发送信息
String sendMessage = sendChatContent.getText().trim();
if (sendMessage.equals("")) {
prompt("无效信息");
return;
}
byte[] buf = sendMessage.getBytes();// /////获得要发送的数据

//设置接收数据的远程IP地址
InetAddress inetAddress = null;
try {
inetAddress = InetAddress.getByName(tfRemoteIP.getText().trim());
} catch (UnknownHostException e) {
prompt("非法远程IP地址");
return;
}

//发送
DatagramPacket dp = new DatagramPacket(buf, 0, buf.length, inetAddress,
remotePort);
try {
ds.send(dp);
} catch (IOException e) {
prompt("网络故障,发送失败");
return;
}
sendChatContent.setText("");// //发送完数据,发送框重置为空

allChatContent.append(new java.text.SimpleDateFormat(
"yy-MM-dd HH:mm:ss").format(new Date())
+ " send to Remote("
+ dp.getAddress()
+ " "
+ dp.getPort()
+ ") :\n");
allChatContent.append(sendMessage + "\n");
ds.close();
}

// 接收数据
class MyRunnable implements Runnable {
byte buf[] = new byte[1024];
DatagramSocket ds = null;
DatagramPacket dp = null;

public void run() {
dp = new DatagramPacket(buf, 0, 1024);
try {
ds = new DatagramSocket(localReceivePort);
} catch (SocketException e1) {
prompt("本地接收端口已被使用");
return;
}
while (true) {
try {
ds.receive(dp);
} catch (IOException e) {
ds.close();
e.printStackTrace();
}
String receiveMessage = new String(dp.getData(), 0, dp
.getLength());
allChatContent.append(new java.text.SimpleDateFormat(
"yy-MM-dd HH:mm:ss").format(new Date())//
+ " from remote("
+ dp.getAddress().getHostAddress()
+ " " + dp.getPort() + ") :\n" + receiveMessage + "\n");
sendChatContent.setCaretPosition(sendChatContent.getText()
.length());

}
}

}

public void receiveMessage() {//
receiveThread = new Thread(new MyRunnable());
receiveThread.start();
}

//异常处理
public void prompt(String promptMessage) {
JOptionPane.showConfirmDialog(null, promptMessage, "友情提示",
JOptionPane.WARNING_MESSAGE);
}

public boolean checkPort(int port) {
return String.valueOf(port).matches("\\d+") && port > 1024
&& port <= 65535;

}

public boolean checkPort(String port) {
return port.matches("\\d+") && Integer.parseInt(port) > 1024
&& Integer.parseInt(port) <= 65535;

}

public boolean checkIP(String ip) {
java.util.regex.Matcher m = Pattern.compile(
"(\\d{1,3}).(\\d{1,3}).(\\d{1,3}).(\\d{1,3})").matcher(ip);
if (m.find()) {
for (int i = 1; i <= 4; i++)
if (Integer.parseInt(m.group(i)) < 0
|| Integer.parseInt(m.group(i)) > 255)
return false;
return true;
}
return true;
}

}


风尘中国 2011-08-26
  • 打赏
  • 举报
回复
我想问个问题,为什么采用UDP实现?
天边的云 2011-08-26
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 d_east 的回复:]
LZ牛B.端口怎么改的?
[/Quote]
你看发送的时候是8088,而自己接受的是8087,8087是一个自己应用程序对外的接口,8088则是另外一个应用程序对外接口,要指定对方的接口,这样另外一方才能收到信息
天边的云 2011-08-26
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 niuniu20008 的回复:]
看着有点累,lz要学习如何贴代码
[/Quote]
好像csdn的问题,我发布的时候看了看,但是一发布就成这个,当然我看见别人好像弄得格式挺好,会学习的
xiaomaoxiaomao11 2011-08-26
  • 打赏
  • 举报
回复
学习中
mhmxd 2011-08-26
  • 打赏
  • 举报
回复
发送按钮的字体改成宋体就是了。。
niuniu20008 2011-08-26
  • 打赏
  • 举报
回复
看着有点累,lz要学习如何贴代码
D_east 2011-08-26
  • 打赏
  • 举报
回复
LZ牛B.端口怎么改的?
小笨熊 2011-08-26
  • 打赏
  • 举报
回复
呵呵,lz不赖,加油

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧