本學期計算機網(wǎng)絡課程要求完成一個TCP和一個UDP的通信程序,我完成了功能的簡單實現(xiàn),下面講講我的TCP程序的實現(xiàn)。
效果展示
連接成功
互發(fā)消息
以下是具體實現(xiàn)過程:
一、項目結(jié)構(gòu)

項目結(jié)構(gòu)
下面說說每個類的具體作用:
TCPClient:TCP客戶端的核心代碼部分;
TCPClientFrame:TCP客戶端的界面搭建;
TCPServer:TCP服務器端的核心代碼部分;
TCPServerFrame:TCP服務器端的界面搭建;
TCPSend:客戶端和服務器端發(fā)送信息的功能實現(xiàn);
ReminderTextAdapter:網(wǎng)上查閱的代碼,非核心內(nèi)容實現(xiàn)部分,主要用于灰色提示字hint功能的實現(xiàn)(swing中的實現(xiàn)方法不太熟悉);
二、完整代碼
1.TCPClient
代碼如下:
package tcpCommunication;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.Socket;
public class TCPClient implements ActionListener, Runnable {
private TCPClientFrame clientFrame;
private Socket socket;
private Thread thread = null;
private DataInputStream inFromServer;
private DataOutputStream outToServer;
public TCPClient() {
JPanel panel = new JPanel();
clientFrame = new TCPClientFrame("TCPClient");
clientFrame.add(panel);
clientFrame.placeComponents(panel);
clientFrame.setVisible(true);
clientFrame.getConnect().addActionListener(e -> {
try {
//host:"127.0.0.1"
String host = clientFrame.getIpField().getText();
//port:6666
int port = Integer.parseInt(clientFrame.getPortField().getText());
socket = new Socket(host, port);
clientFrame.getTextArea().append("[Connect] : Connect…\n");
inFromServer = new DataInputStream(socket.getInputStream());
outToServer = new DataOutputStream(socket.getOutputStream());
//new TCPSend(socket, "客戶端").sendMessage();
thread = new Thread(this);
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
} catch (IOException ex) {
ex.printStackTrace();
}
});
clientFrame.getTransmit().addActionListener(this);
System.out.println("TCP客戶端準備就緒\n");
}
public static void main(String[] args) {
new TCPClient();
}
//向服務器端發(fā)送數(shù)據(jù)
@Override
public void actionPerformed(ActionEvent e) {
String send = clientFrame.getSendField().getText();
new TCPSend(send, outToServer, clientFrame.getTextArea(),
"Client").sendMessages();
}
//使用線程處理客戶端接收服務器端的數(shù)據(jù)
@Override
public void run() {
while (true) {
try {
clientFrame.getTextArea().append("[Server send] : " + inFromServer.readUTF() + "\n");
Thread.sleep(100);
} catch (IOException | InterruptedException e) {
//e.printStackTrace();
System.out.println("客戶端與服務器連接中斷\n");
break;
}
}
}
}
2.TCPClientFrame
代碼如下:
package tcpCommunication;
import udpCommunication.ReminderTextAdapter;
import javax.swing.*;
import java.awt.*;
public class TCPClientFrame extends JFrame {
private static JTextField ipField;
private static JTextField portField;
private static JTextField sendField;
private static JTextArea textArea;
private static JButton connect;
private static JButton transmit;
public TCPClientFrame(String title) {
setSize(700, 480);
setLocationRelativeTo(null);//居中顯示
setResizable(false);//設置不允許改變窗體大小
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle(title);
}
public JTextField getIpField() {
return ipField;
}
public JTextField getPortField() {
return portField;
}
public JTextField getSendField() {
return sendField;
}
public JTextArea getTextArea() {
return textArea;
}
public JButton getConnect() {
return connect;
}
public JButton getTransmit() {
return transmit;
}
public void placeComponents(JPanel panel) {
panel.setLayout(null);
Font font1 = new Font("宋體", Font.BOLD, 18);
Font font2 = new Font("宋體", Font.PLAIN, 18);
//創(chuàng)建JLabel
JLabel ip = new JLabel("IP");
ip.setFont(font1);//設置JLabel的字體
ip.setBounds(105, 35, 120, 38);
panel.add(ip);
JLabel port = new JLabel("Port");
port.setFont(font1);
port.setBounds(105, 80, 120, 38);
panel.add(port);
JLabel send = new JLabel("Send");
send.setFont(font1);
send.setBounds(105, 125, 120, 38);
panel.add(send);
JLabel text = new JLabel("Text");
text.setFont(font1);
text.setBounds(105, 170, 120, 38);
panel.add(text);
//創(chuàng)建文本域
ipField = new JTextField(30);
ipField.setFont(font2);
ipField.addFocusListener(new tcpCommunication.ReminderTextAdapter(ipField, "默認:127.0.0.1"));
ipField.setBounds(180, 35, 380, 38);
panel.add(ipField);
portField = new JTextField(30);
portField.setFont(font2);
portField.addFocusListener(new ReminderTextAdapter(portField, "port:"));
portField.setBounds(180, 80, 380, 38);
panel.add(portField);
sendField = new JTextField(30);
sendField.setFont(font2);
sendField.addFocusListener(new ReminderTextAdapter(sendField, "請輸入要發(fā)送的信息:"));
sendField.setBounds(180, 125, 380, 38);
panel.add(sendField);
textArea = new JTextArea();
textArea.setFont(font2);
textArea.setBounds(180, 170, 380, 170);
textArea.setEditable(false);
textArea.setLineWrap(false);
panel.add(textArea);
//給textArea添加滾動條
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(180, 170, 380, 170);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
panel.add(scrollPane);
scrollPane.setViewportView(textArea);
//添加兩個按鈕
connect = new JButton("連接");
connect.setFont(font1);
connect.setBounds(140, 360, 115, 40);
panel.add(connect);
transmit = new JButton("發(fā)送");
transmit.setFont(font1);
transmit.setBounds(440, 360, 115, 40);
panel.add(transmit);
}
}
3.TCPServer
代碼如下:
package tcpCommunication;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer implements ActionListener, Runnable {
private TCPServerFrame serverFrame;
private ServerSocket server;
private Socket socket;
private Thread thread = null;
private DataInputStream inFromClient;
private DataOutputStream outToClient;
public TCPServer() {
serverFrame = new TCPServerFrame("TCPServer");
JPanel panel = new JPanel();
serverFrame.add(panel);
serverFrame.placeComponents(panel);
serverFrame.setVisible(true);
//port:6666
serverFrame.getMonitor().addActionListener(e -> {
try {
int port = Integer.parseInt(serverFrame.getPortField().getText());
server = new ServerSocket(port);
serverFrame.getTextArea().append("[Listen] : Listen…\n");
//獲取客戶端的socket
socket = server.accept();
serverFrame.getTextArea().append("[Accept] : Accept OK.\n");
inFromClient = new DataInputStream(socket.getInputStream());
outToClient = new DataOutputStream(socket.getOutputStream());
thread = new Thread(this);
//創(chuàng)建子線程處理客戶端輸入信息
//new TCPServerThread(socket).start();
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
} catch (IOException ex) {
ex.printStackTrace();
}
});
serverFrame.getTransmit().addActionListener(this);
System.out.println("TCP服務器準備就緒\n");
}
public static void main(String[] args) {
new TCPServer();
}
//向客戶端發(fā)送數(shù)據(jù)
@Override
public void actionPerformed(ActionEvent e) {
String send = serverFrame.getSendField().getText();
new TCPSend(send, outToClient, serverFrame.getTextArea(),
"Server").sendMessages();
}
//使用線程處理服務器端接收客戶端的數(shù)據(jù)
@Override
public void run() {
while (true) {
try {
serverFrame.getTextArea().append("[Client send] : " + inFromClient.readUTF() + "\n");
Thread.sleep(100);
} catch (IOException | InterruptedException e) {
//e.printStackTrace();
System.out.println("服務器與客戶端連接中斷\n");
break;
}
}
}
}
4.TCPServerFrame
代碼如下:
package tcpCommunication;
import udpCommunication.ReminderTextAdapter;
import javax.swing.*;
import java.awt.*;
public class TCPServerFrame extends JFrame {
private static JTextField portField;
private static JTextField sendField;
private static JTextArea textArea;
private static JButton monitor;
private static JButton transmit;
public TCPServerFrame(String title) {
setSize(700, 480);
setLocationRelativeTo(null);//居中顯示
setResizable(false);//設置不允許改變窗體大小
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle(title);
}
public JTextField getPortField() {
return portField;
}
public JTextField getSendField() {
return sendField;
}
public JTextArea getTextArea() {
return textArea;
}
public JButton getMonitor() {
return monitor;
}
public JButton getTransmit() {
return transmit;
}
public void placeComponents(JPanel panel) {
panel.setLayout(null);
Font font1 = new Font("宋體", Font.BOLD, 18);
Font font2 = new Font("宋體", Font.PLAIN, 18);
//創(chuàng)建JLabel
JLabel port = new JLabel("Port");
port.setFont(font1);
port.setBounds(105, 45, 120, 38);
panel.add(port);
JLabel send = new JLabel("Send");
send.setFont(font1);
send.setBounds(105, 100, 120, 38);
panel.add(send);
JLabel text = new JLabel("Text");
text.setFont(font1);
text.setBounds(105, 165, 120, 38);
panel.add(text);
//創(chuàng)建文本域
portField = new JTextField(30);
portField.setFont(font2);
portField.addFocusListener(new ReminderTextAdapter(portField, "port:"));
portField.setBounds(180, 45, 380, 38);
panel.add(portField);
sendField = new JTextField(30);
sendField.setFont(font2);
sendField.addFocusListener(new ReminderTextAdapter(sendField, "請輸入要發(fā)送的信息:"));
sendField.setBounds(180, 100, 380, 38);
panel.add(sendField);
textArea = new JTextArea();
textArea.setFont(font2);
textArea.setBounds(180, 160, 380, 170);
textArea.setEditable(false);
textArea.setLineWrap(false);
panel.add(textArea);
//給textArea添加滾動條
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(180, 160, 380, 170);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
panel.add(scrollPane);
scrollPane.setViewportView(textArea);
//添加兩個按鈕
monitor = new JButton("監(jiān)聽");
monitor.setFont(font1);
monitor.setBounds(140, 360, 115, 40);
panel.add(monitor);
transmit = new JButton("發(fā)送");
transmit.setFont(font1);
transmit.setBounds(440, 360, 115, 40);
panel.add(transmit);
}
}
5.TCPSend
代碼如下:
package tcpCommunication;
import javax.swing.*;
import java.io.DataOutputStream;
import java.io.IOException;
public class TCPSend {
private String send;
private DataOutputStream dataOutputStream;
private JTextArea textArea;
private String sendObject;
public TCPSend(String send, DataOutputStream dataOutputStream, JTextArea textArea, String sendObject) {
this.send = send;
this.dataOutputStream = dataOutputStream;
this.textArea = textArea;
this.sendObject = sendObject;
}
public void sendMessages() {
if (send.length() > 0) {
try {
dataOutputStream.writeUTF(send);
dataOutputStream.flush();
textArea.append("\t\t [" + sendObject + " send] : " + send + "\n");
} catch (IOException ex) {
textArea.append("Your message : “" + send + "”failed to send!\n");
}
}
}
}
6.ReminderTextAdapter(參考別人的,非原創(chuàng))
代碼如下:
package tcpCommunication;
import javax.swing.*;
import java.awt.*;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
public class ReminderTextAdapter extends FocusAdapter {
//JTextField提示文字通用方法
JTextField textField;
String reminderString;
//初始化
public ReminderTextAdapter(JTextField textField, String reminderString) {
this.textField = textField;
this.reminderString = reminderString;
}
//焦點獲得
@Override
public void focusGained(FocusEvent e) {
String tempString = textField.getText();
//String tempString = this.getText();
if (tempString.equals(reminderString)) {
textField.setText("");
textField.setForeground(Color.BLACK);
}
}
//焦點失去
@Override
public void focusLost(FocusEvent e) {
String tempString = textField.getText();
if (tempString.equals("")) {
textField.setForeground(Color.GRAY);
textField.setText(reminderString);
}
}
}
總結(jié)
該項目簡單的實現(xiàn)了TCP客戶端和服務器端的通信,但是功能比較簡單,頁面也比較簡潔,沒有實現(xiàn)多個客戶端互聊的功能等,還有待完善。
CSDN文章鏈接:https://blog.csdn.net/twj1248445531/article/details/110947510(這是我CSDN里寫的,有目錄,簡書好像不行,不支持網(wǎng)頁標簽)