基本实现思路: 首先得用Java Swing 编程写一个聊天界面,该界面需要包含以下元素
聊天界面主要的就这三大组件
实现步骤,用一个JScrollPane
中间层容器来装一个文本框原子组件,该文本框设置为不可编辑,还要定义一个JPanel
中间容器来装两个原子组件Button
和JTextField
,就是我们的输入文本框和发送按钮,然后再给Button
和JTextField
注册一个监听器,然后实现对应的响应函数,这里发生的是ActionListener
,所以要实现的响应函数是actionPerformed
super(ID);
myID = ID;
this.port = port;
ta = new JTextArea();
ta.setEditable(false);
sp = new JScrollPane(ta);
this.setSize(330,400);
this.setResizable(false);
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(Exception e)
{
System.out.println("UI error");
}
this.getContentPane().add(sp,"Center");
p = new JPanel();
this.getContentPane().add(p,"South");
send = new JButton("发送");
tf = new JTextField(20);
tf.requestFocus();
p.add(tf);
p.add(send);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
send.addActionListener(this);
tf.addActionListener(this);
上面的代码就是实现图形界面的完整代码,看不懂的可以去看一下Java Swing编程
实现网络聊天的另一个关键步骤就是建立网络连接
网络连接中有客户端和服务器,我们需要分别实现这两个端
客户端只要构建一个socket对象,然后向目标ip地址以及对应端口号发起连接就可以了
try
{
mySocket=new Socket(IP,port); //目标IP地址和对应的端口号
os = new PrintWriter(mySocket.getOutputStream());
//获得输出流,以便将信息发送到目标地址
is = new BufferedReader(new
InputStreamReader(mySocket.getInputStream()));
//输入流,将对方发送的信息读取出来
}
catch(Exception e)
{
System.out.println("Error:in Client Socket"+e);
}
服务器端就要定义一个ServerSocket对象,然后使用该对象的wait方法等待来自客户端的socket连接请求,得到对应的socket对象,后面就是跟客户端基本相同的操作
if(isServer)
{
try
{
server=null;
try
{
server=new ServerSocket(port);
//使用端口号port初始化一个ServerSocket对象
}
catch(Exception e)
{
System.out.println("can not listen to:"+e);
}
mySocket=null;
try
{
mySocket=server.accept(); //等待来自客户端的socket连接请求
}
catch(Exception e)
{
System.out.println("Error:"+e);
}
is = new BufferedReader(new
InputStreamReader(mySocket.getInputStream()));
os = new PrintWriter(mySocket.getOutputStream());
//跟客户端一样,用来接收和发送信息
}
catch(Exception e)
{
System.out.println("Error:in server client socket"+e);
}
}
现在我们要实现的就是将接收到的信息输出到聊天区域ta
中去
while(true)
{
try
{
line = is.readLine(); //获得输入流中的信息
date = new Date(); //获得日期
SimpleDateFormat formatter = new
SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //定义标准格式
String currentTime = formatter.format(date); //将日期标准格式化
s+=currentTime+""+remoteID+"说:\n"+line+"\n"; //将所有信息组合在一起
ta.setText(s); //显示到ta文本框中
}
catch(Exception e)
{
System.out.println("Error:in receive remote information"+e);
}
}
现在就是实现网络聊天程序的最后一步,也就是响应函数,当我们点击发送时,就要将我们输入到JTextField
中的内容输出到socket对象去
public void actionPerformed(ActionEvent e)
{
date=new Date(); //获得日期
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String currentTime = formatter.format(date);
s+=currentTime+""+myID+"说:\n"+tf.getText()+"\n";
ta.setText(s); //将我们要发送的信息输出到ta文本框
os.println(tf.getText()); //将要发送的信息发送出去
os.flush(); //上面是发送到缓冲区,这一步确保信息被发送出去
tf.setText(""); //将我们的输入框置为空
tf.requestFocus();
}
完整代码:
package net;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.*;
public class ChatFrame extends JFrame implements ActionListener{
JTextField tf;
JTextArea ta;
JScrollPane sp;
JButton send;
JPanel p;
int port;
String s="";
String myID;
Date date;
ServerSocket server;
Socket mySocket;
BufferedReader is;
PrintWriter os;
String line;
public ChatFrame(String ID, String remoteID, String IP, int port, boolean isServer)
{
super(ID);
myID = ID;
this.port = port;
ta = new JTextArea();
ta.setEditable(false);
sp = new JScrollPane(ta);
this.setSize(330,400);
this.setResizable(false);
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(Exception e)
{
System.out.println("UI error");
}
this.getContentPane().add(sp,"Center");
p = new JPanel();
this.getContentPane().add(p,"South");
send = new JButton("发送");
tf = new JTextField(20);
tf.requestFocus();
p.add(tf);
p.add(send);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
send.addActionListener(this);
tf.addActionListener(this);
if(isServer)
{
try
{
server=null;
try
{
server=new ServerSocket(port);
}
catch(Exception e)
{
System.out.println("can not listen to:"+e);
}
mySocket=null;
try
{
mySocket=server.accept();
}
catch(Exception e)
{
System.out.println("Error:"+e);
}
is = new BufferedReader(new
InputStreamReader(mySocket.getInputStream()));
os = new PrintWriter(mySocket.getOutputStream());
}
catch(Exception e)
{
System.out.println("Error:in server client socket"+e);
}
}
else
{
try
{
mySocket=new Socket(IP,port);
os = new PrintWriter(mySocket.getOutputStream());
is = new BufferedReader(new
InputStreamReader(mySocket.getInputStream()));
}
catch(Exception e)
{
System.out.println("Error:in Client Socket"+e);
}
}
while(true)
{
try
{
line = is.readLine();
date = new Date();
SimpleDateFormat formatter = new
SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String currentTime = formatter.format(date);
s+=currentTime+""+remoteID+"说:\n"+line+"\n";
ta.setText(s);
}
catch(Exception e)
{
System.out.println("Error:in receive remote information"+e);
}
}
}
public void actionPerformed(ActionEvent e)
{
date=new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String currentTime = formatter.format(date);
s+=currentTime+""+myID+"说:\n"+tf.getText()+"\n";
ta.setText(s);
os.println(tf.getText());
os.flush();
tf.setText("");
tf.requestFocus();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
我们可以定义两个对象来测试一下
客户端
package net;
public class ChatClientFrame {
public static void main(String[] args) {
// TODO Auto-generated method stub
ChatFrame client = new
ChatFrame("dog","cat","127.0.0.1",2009,false);
}
}
服务器端
package net;
public class ChatServerFrame {
public static void main(String[] args) {
// TODO Auto-generated method stub
ChatFrame cserver = new
ChatFrame("cat","dog","127.0.0.1",2009,true);
}
}
补充一点:如果要在两个电脑上运行,需要给出服务器端的ip
地址,可以使用ipconfig/all
查看电脑的ip
地址
效果图:
清华大学Java教程