Java实战之基于TCP实现简单聊天程序
作者:howard2005 时间:2022-09-01 17:09:20
一、如何实现TCP通信
要实现TCP通信需要创建一个服务器端程序和一个客户端程序,为了保证数据传输的安全性,首先需要实现服务器端程序,然后在编写客户端程序。
在本机运行服务器端程序,在远程机运行客户端程序
本机的IP地址:192.168.129.222
远程机的IP地址:192.168.214.213
二、编写C/S架构聊天程序
1.编写服务器端程序 - Server.java
在net.hw.network包里创建Server类
package net.hw.network;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 功能:服务器端
* 作者:华卫
* 日期:2022年03月18日
*/
public class Server extends JFrame {
static final int PORT = 8136;
static final String HOST_IP = "192.168.129.222";
private JPanel panel1, panel2;
private JTextArea txtContent, txtInput, txtInputIP;
private JScrollPane panContent, panInput;
private JButton btnClose, btnSend;
private ServerSocket serverSocket;
private Socket socket;
private DataInputStream netIn;
private DataOutputStream netOut;
public static void main(String[] args) {
new Server();
}
public Server() {
super("服务器");
//创建组件
panel1 = new JPanel();
panel2 = new JPanel();
txtContent = new JTextArea(15, 60);
txtInput = new JTextArea(3, 60);
panContent = new JScrollPane(txtContent, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
panInput = new JScrollPane(txtInput, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
btnClose = new JButton("关闭");
btnSend = new JButton("发送");
//添加组件
getContentPane().add(panContent, "Center");
getContentPane().add(panel1, "South");
panel1.setLayout(new GridLayout(0, 1));
panel1.add(panInput);
panel1.add(panel2);
panel2.add(btnSend);
panel2.add(btnClose);
//设置组件属性
txtContent.setEditable(false);
txtContent.setFont(new Font("宋体", Font.PLAIN, 13));
txtInput.setFont(new Font("宋体", Font.PLAIN, 15));
txtContent.setLineWrap(true);
txtInput.setLineWrap(true);
txtInput.requestFocus();
setSize(450, 350);
setLocation(50, 200);
setResizable(false);
setVisible(true);
//等候客户请求
try {
txtContent.append("服务器已启动...\n");
serverSocket = new ServerSocket(PORT);
txtContent.append("等待客户请求...\n");
socket = serverSocket.accept();
txtContent.append("连接一个客户。\n" + socket + "\n");
netIn = new DataInputStream(socket.getInputStream());
netOut = new DataOutputStream(socket.getOutputStream());
} catch (IOException e1) {
e1.printStackTrace();
}
/
//注册 * ,编写事件代码
txtContent.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
displayClientMsg();
}
});
txtInput.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
displayClientMsg();
}
});
panel2.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
displayClientMsg();
}
});
txtInput.addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent e) {
displayClientMsg();
}
});
txtInput.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent e) {
displayClientMsg();
}
});
btnSend.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
String serverMsg = txtInput.getText();
if (!serverMsg.trim().equals("")) {
txtContent.append("服务器>" + serverMsg + "\n");
netOut.writeUTF(serverMsg);
} else {
JOptionPane.showMessageDialog(null, "不能发送空信息!", "服务器", JOptionPane.WARNING_MESSAGE);
}
txtInput.setText("");
txtInput.requestFocus();
} catch (IOException ie) {
ie.printStackTrace();
}
}
});
btnClose.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
try {
netIn.close();
netOut.close();
socket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
System.exit(0);
}
});
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
try {
netIn.close();
netOut.close();
socket.close();
serverSocket.close();
} catch (IOException ie) {
ie.printStackTrace();
}
System.exit(0);
}
public void windowActivated(WindowEvent e) {
txtInput.requestFocus();
}
});
}
//显示客户端信息
void displayClientMsg() {
try {
if (netIn.available() > 0) {
String clientMsg = netIn.readUTF();
txtContent.append("客户端>" + clientMsg + "\n");
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
2.编写客户端程序 - Client.java
在net.hw.network包里创建Client类
package net.hw.network;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
/**
* 功能:客户端
* 作者:华卫
* 日期:2022年03月18日
*/
public class Client extends JFrame {
private JPanel panel1, panel2;
private JTextArea txtContent, txtInput;
private JScrollPane panContent, panInput;
private JButton btnClose, btnSend;
private Socket socket;
private DataInputStream netIn;
private DataOutputStream netOut;
public static void main(String[] args) {
new Client();
}
public Client() {
super("客户端");
//创建组件
panel1 = new JPanel();
panel2 = new JPanel();
txtContent = new JTextArea(15, 60);
txtInput = new JTextArea(3, 60);
panContent = new JScrollPane(txtContent, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
panInput = new JScrollPane(txtInput, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
btnClose = new JButton("关闭");
btnSend = new JButton("发送");
//添加组件
getContentPane().add(panContent, "Center");
getContentPane().add(panel1, "South");
panel1.setLayout(new GridLayout(0, 1));
panel1.add(panInput);
panel1.add(panel2);
panel2.add(btnSend);
panel2.add(btnClose);
//设置组件属性
txtContent.setEditable(false);
txtContent.setFont(new Font("宋体", Font.PLAIN, 13));
txtInput.setFont(new Font("宋体", Font.PLAIN, 15));
txtContent.setLineWrap(true);
txtInput.setLineWrap(true);
txtInput.requestFocus();
setSize(450, 350);
setLocation(550, 200);
setResizable(false);
setVisible(true);
//连接服务器
try {
txtContent.append("连接服务器...\n");
socket = new Socket(Server.HOST_IP, Server.PORT);
txtContent.append("连接服务器成功。\n" + socket + "\n");
netIn = new DataInputStream(socket.getInputStream());
netOut = new DataOutputStream(socket.getOutputStream());
} catch (IOException e1) {
JOptionPane.showMessageDialog(null, "服务器连接失败!\n请先启动服务器程序!", "客户端", JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
/
//注册 * ,编写事件代码
txtContent.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
displayServerMsg();
}
});
txtInput.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
displayServerMsg();
}
});
panel2.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
displayServerMsg();
}
});
txtInput.addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent e) {
displayServerMsg();
}
});
txtInput.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent e) {
displayServerMsg();
}
});
btnSend.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
String clientMsg = txtInput.getText();
if (!clientMsg.trim().equals("")) {
netOut.writeUTF(clientMsg);
txtContent.append("客户端>" + clientMsg + "\n");
} else {
JOptionPane.showMessageDialog(null, "不能发送空信息!", "客户端", JOptionPane.WARNING_MESSAGE);
}
txtInput.setText("");
txtInput.requestFocus();
} catch (IOException ie) {
ie.printStackTrace();
}
}
});
btnClose.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
netIn.close();
netOut.close();
socket.close();
} catch (IOException ie) {
ie.printStackTrace();
}
System.exit(0);
}
});
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
try {
netIn.close();
netOut.close();
socket.close();
} catch (IOException ie) {
ie.printStackTrace();
}
System.exit(0);
}
public void windowActivated(WindowEvent e) {
txtInput.requestFocus();
}
});
}
//显示服务端信息
void displayServerMsg() {
try {
if (netIn.available() > 0) {
String serverMsg = netIn.readUTF();
txtContent.append("服务器>" + serverMsg + "\n");
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
3.测试服务器端与客户端能否通信
在本机[192.168.129.222]上启动服务器端
在远程机[192.168.214.213]上启动客户端
显示连接服务器[192.168.129.222]成功,切换到服务器端查看,显示连接了一个客户[192.168.214.213]
此时,服务器端和客户端就可以相互通信了
4.程序优化思路 - 服务器端采用多线程
其实,很多服务器端程序都是允许被多个应用程序访问的,例如门户网站可以被多个用户同时访问,因此服务器端都是多线程的。
来源:https://blog.csdn.net/howard2005/article/details/123573139
标签:Java,TCP,聊天
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
Android提高之MediaPlayer音视频播放
2021-05-29 08:44:37
![](https://img.aspxhome.com/file/2023/2/102602_0s.jpg)
关于java String中intern的深入讲解
2023-01-24 18:18:36
Mybatis-Plus 条件构造器示例详解
2023-06-26 06:45:17
![](https://img.aspxhome.com/file/2023/9/118809_0s.png)
Linux环境g++编译GDAL动态库操作方法
2022-02-23 09:41:45
![](https://img.aspxhome.com/file/2023/4/109784_0s.jpg)
java 键盘输入一个数,输出数组中指定元素的示例
2023-11-24 20:31:14
Android5.0+ CollapsingToolbarLayout使用详解
2022-07-01 01:20:25
![](https://img.aspxhome.com/file/2023/8/98648_0s.jpg)
Java开发工具IntelliJ IDEA安装图解
2022-06-14 02:30:20
![](https://img.aspxhome.com/file/2023/4/69934_0s.png)
基于Android引入IjkPlayer无法播放mkv格式视频的解决方法
2023-02-24 22:32:35
![](https://img.aspxhome.com/file/2023/7/119087_0s.jpg)
一文带你搞懂Java中Get和Post的使用
2023-04-16 23:57:24
![](https://img.aspxhome.com/file/2023/6/116826_0s.png)
Android实现纸飞机的简单操作
2022-05-16 12:26:04
Java 提取照片的EXIF信息批量重命名
2023-10-05 14:11:28
![](https://img.aspxhome.com/file/2023/8/80838_0s.png)
C#多线程之线程池ThreadPool用法
2021-07-21 06:28:40
![](https://img.aspxhome.com/file/2023/1/108771_0s.jpg)
mybatis plus新增(insert)数据获取主键id的问题
2023-08-09 10:50:52
细谈java同步之JMM(Java Memory Model)
2023-11-23 13:09:33
![](https://img.aspxhome.com/file/2023/3/59973_0s.png)
OpenHarmony实现类Android短信验证码及倒计时流程详解
2021-11-14 10:55:26
![](https://img.aspxhome.com/file/2023/0/110670_0s.png)
Spring EL表示式的运用@Value说明
2023-03-05 02:33:19
java实现邮件发送
2022-06-03 02:48:20
![](https://img.aspxhome.com/file/2023/2/68762_0s.jpg)
Android Bitmap和Drawable的对比
2021-11-16 06:03:41
关于工厂方法模式的Java实现
2021-12-20 18:06:13
java 集合之实现类ArrayList和LinkedList的方法
2023-09-03 05:41:40