Java简单聊天工具
双人聊天工具
教程链接: https://www.bilibili.com/video/av57820725/?p=1.
代码如下
//下面是客户端,文件名ClinetChatMain.java
package cn.itcast.chat;
import java.awt.BorderLayout;
import java.awt.BufferCapabilities;
import java.awt.RenderingHints.Key;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Properties;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class ClientChatMain extends JFrame implements ActionListener ,KeyListener{
public static void main(String[] args) {
//调用构造方法
new ClientChatMain();
}
//属性
//文本域
private JTextArea jta;
//滚动条
private JScrollPane jsp;
//面板
private JPanel jp;
//文本框
private JTextField jtf;
//按钮
private JButton jb;
private BufferedWriter bufferedWriter = null;
//创建IP和端口号的静态变量
private static int clientPort;
private static String clientIP;
static{
Properties properties = new Properties();
try {
properties.load(new FileReader("chat.properties"));
clientIP = properties.getProperty("clientIP");
clientPort = Integer.parseInt(properties.getProperty("clientPort"));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//构造方法
public ClientChatMain() {
//初始化组件
//文本域
jta = new JTextArea();
jta.setEditable(false);//设置文本域不可以编辑
//注意:需要将文本域添加到滚动条上,实现滚动效果。
jsp = new JScrollPane(jta);
//面板
jp = new JPanel();
//文本框,参数是大小
jtf = new JTextField(10);
//按钮
jb = new JButton("发送");
//需要将文本框与按钮添加到面板中
jp.add(jtf);
jp.add(jb);
//窗口 第一个参数是添加滚动条和面板,后面是布局位置
this.add(jsp,BorderLayout.CENTER);
this.add(jp,BorderLayout.SOUTH);
//注意需要设置标题,大小,位置,关闭,是否可见
//标题
this.setTitle("QQ聊天客户端");
//大小
this.setSize(300,300);
//位置
this.setLocation(300,300);
//关闭窗口的时候,程序就退出
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//窗体显示
this.setVisible(true);
//按钮帮定监听事件
jb.addActionListener(this);
jtf.addKeyListener(this);
/*************TCP 客户端 开始******************/
//1.创建一个客户端套接字
try {
Socket clientSocket = new Socket(clientIP,clientPort);//前一个是ip地址,后面是服务端的端口号
//2.获取socket通道的输入流
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
//3.获取socket通道的输出流
bufferedWriter = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
//循环读取数据,并拼接到文本域中
String line = null;
while((line = bufferedReader.readLine()) != null){
jta.append(line + System.lineSeparator());
}
//4.关闭通道
clientSocket.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/*************TCP 客户端 结束******************/
}
//监听点击事件
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
// //1.获取文本框内容
// String text = jtf.getText();
// //2.拼接文本域内容
// text = "客户端对服务端说: " + text +System.lineSeparator();
// //3.自己显示
// jta.append(text);
//
// //4.输出
// try {
// bufferedWriter.write(text);
// //bufferedWriter.newLine();
// bufferedWriter.flush();
// jtf.setText("");
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
sendDataSocket();
}
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if(e.getKeyCode() == KeyEvent.VK_ENTER){
sendDataSocket();
}
}
@Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
//实现将数据发送到socket
private void sendDataSocket () {
String text = jtf.getText();
text = "客户端对服务端说: " + text + System.lineSeparator();
jta.append(text);
try {
bufferedWriter.write(text);
bufferedWriter.flush();
jtf.setText("");
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
//下面是服务端,文件名是ServerChatMain.java
package cn.itcast.chat;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.im.InputContext;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;
import javax.sound.sampled.Line;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
//如果有界面能显示,就要继承JFrame,变成窗体类
//1.定义JFrame中的组件
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
/*一个类如果要有界面运行就必须继承自JFrame,此时,该类就被称为一个“窗体类”
* 定义JFrame窗口中的组件
* 在构造方法中初始化窗体的组件
* 使用网络编程完成数据的传输
* 点击“发送”按钮的监听点击事件
* 实现回车键发送数据 给文本框绑定事件
* **/
public class ServerChatMain extends JFrame implements ActionListener,KeyListener{
public static void main(String[] args) {
//调用构造方法
new ServerChatMain();
}
//属性
//文本域
private JTextArea jta;
//滚动条
private JScrollPane jsp;
//面板
private JPanel jp;
//文本框
private JTextField jtf;
//按钮
private JButton jb;
//将BufferWriter变成成员变量,这样就能在监听方法actionPerformed中监听后输出
private BufferedWriter bufferedWriter = null;
//服务端的端口号
private static int serverPort;
//使用 static静态代码块读取外部配置文件
//static的特点:在类加载的时候自动执行, 静态代码块在程序中仅会被执行一次
static{
Properties properties = new Properties();
try {
//加载
properties.load(new FileReader("chat.properties"));
//给属性赋值
serverPort = Integer.parseInt(properties.getProperty("serverPort"));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//构造方法
public ServerChatMain() {
//初始化组件
//文本域
jta = new JTextArea();
jta.setEditable(false);//设置文本域不可以编辑
//注意:需要将文本域添加到滚动条上,实现滚动效果。
jsp = new JScrollPane(jta);
//面板
jp = new JPanel();
//文本框,参数是大小
jtf = new JTextField(10);
//按钮
jb = new JButton("发送");
//需要将文本框与按钮添加到面板中
jp.add(jtf);
jp.add(jb);
//窗口 第一个参数是添加滚动条和面板,后面是布局位置
this.add(jsp,BorderLayout.CENTER);
this.add(jp,BorderLayout.SOUTH);
//注意需要设置标题,大小,位置,关闭,是否可见
//标题
this.setTitle("QQ聊天服务端");
//大小
this.setSize(300,300);
//位置
this.setLocation(600,300);
//关闭窗口的时候,程序就退出
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//窗体显示
this.setVisible(true);
/*************TCP 服务端 开始******************/
//给发送按钮绑定一个监听点击事件
jb.addActionListener(this);
jtf.addKeyListener(this);
try {
//1.创建一个服务端套接字
ServerSocket serverSocket = new ServerSocket(serverPort);
//2.等待客户端的连接
Socket socket = serverSocket.accept();
//3.获取socket通道的输入流(输入流是实现读取数据的,方式是一行一行读取,因此选择的类最后啊是BufferReader -> readLine)
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
//4.获取socket通道的输出流,(实现写出数据,最好是写一行换一行,刷新,所以用类BufferWiter -> newLine();)
bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//下面实现一行一行读,循环读取数据,并拼接到文本域中
String line = null;
while((line = bufferedReader.readLine()) !=null){
//将读取数据拼接到文本域中显示
jta.append(line + System.lineSeparator());//line + 换行
}
//5.关闭通道(serverSocket)
serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/*************TCP 服务端 结束******************/
}
//下面是监听内容
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
//System.out.print("发送按钮被点击了");
//1.获取文本框中的内容
//String text= jtf.getText();
//2.拼接发送的数据内容
sendDataSocket();
}
//下面是实现文本框与回车键绑定
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
//辨别是否是回车键
if(e.getKeyCode() == KeyEvent.VK_ENTER){
//发送数据到socket中
sendDataSocket();
}
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
//定义方法,实现发动数据到socket中
private void sendDataSocket(){
String text = jtf.getText();
text = "服务端对客户端说: " + text + System.lineSeparator();
jta.append(text);
try {
bufferedWriter.write(text);
bufferedWriter.flush();
jtf.setText("");
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
//行为
}
在包内创建一个chat.properties文件,用于说明端口号和IP
//文件名是chat.properties
serverPort = 8888
clientIP = 127.0.0.1
clientPort = 8888
所以完成之后的文件放置位置如下
将上面的简单总结一下
创建
服务端的创建
1,利用ServerSocket(int port)函数创建socket。
2,利用accept函数监听客户端是否连接。
3,利用close函数关闭服务端。
客户端的创建
1,利用Socket(String ip,int port)创建socket,这的端口号port必须与服务端的一样,为了能监听到。
2,利用close函数关闭客户端。
代码如下:
//服务端
ServerSocket server = new ServerSocket(8888);
Socket socket = server.accept();
server.close();
//客户端
Socket client = new Scoket("127.0.0.1",8888);
client.close();
接发消息
待更