首页 > 其他分享 >Socket支持下的点对点通信的实现(服务端与客户端注释)

Socket支持下的点对点通信的实现(服务端与客户端注释)

时间:2023-11-20 17:44:55浏览次数:33  
标签:Socket 输入框 add 添加 new 客户端 public 服务端 panel

服务端程序

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;

import javax.swing.*;

public class Server extends JFrame implements ActionListener {
	ServerSocket ss = null; // ServerSocket对象
	Socket s = null; // Socket对象
	private DataInputStream is = null; // 输入流
	private DataOutputStream os = null; // 输出流
	private boolean connected = false; // 是否连接标志
	JLabel ipLabel = new JLabel(); // 显示本机IP地址的标签
	JLabel portLabel = new JLabel("端口"); // 显示端口号的标签
	JTextField portTextField = new JTextField("8000"); // 端口号输入框
	JButton listenButton = new JButton("监听"); // 监听按钮
	JButton closeButton = new JButton("关闭"); // 关闭按钮
	JPanel panel = new JPanel(); // 包含各种控件的面板
	JTextField inputTextField = new JTextField(); // 输入框
	JTextArea contentTextArea = new JTextArea(); // 显示接收到的数据的文本区域
	Thread recvThread = new Thread(new RecvThread()); // 接收数据的线程

	// 构造函数
	public Server() {
		setTitle("服务器端"); // 窗口标题
		setLayout(new BorderLayout()); // 设置布局为边界布局
		panel.setLayout(new FlowLayout()); // 面板使用流式布局
		try {
			// 获取本机IP地址并显示
			ipLabel.setText("本机IP信息:" + InetAddress.getLocalHost().toString());
		} catch (HeadlessException e) {
			e.printStackTrace();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
		panel.add(ipLabel); // 添加IP地址标签到面板
		panel.add(portLabel); // 添加端口号标签到面板
		panel.add(portTextField); // 添加端口号输入框到面板
		panel.add(listenButton); // 添加监听按钮到面板
		panel.add(closeButton); // 添加关闭按钮到面板
		add(panel, BorderLayout.NORTH); // 将面板添加到窗口北部
		add(new JScrollPane(contentTextArea), BorderLayout.CENTER); // 将文本区域添加到窗口中央,可以滚动
		add(inputTextField, BorderLayout.SOUTH); // 将输入框添加到窗口南部
		listenButton.addActionListener(this); // 监听按钮添加事件监听器
		closeButton.addActionListener(this); // 关闭按钮添加事件监听器
		inputTextField.addActionListener(this); // 输入框添加事件监听器

		addWindowListener(new WindowAdapter() { // 窗口关闭事件监听器,关闭程序时同时断开连接
			@Override
			public void windowClosing(WindowEvent e) {
				disconnect();
			}
		});
		setSize(500, 300); // 窗口大小
		setLocationRelativeTo(null); // 将窗口位于屏幕的中央
		setVisible(true); // 显示窗口
	}

	// 开始监听
	public void start() {
		try {
			int port = Integer.parseInt(portTextField.getText()); // 获取输入的端口号
			connected = true; // 标记已连接
			ss = new ServerSocket(port); // 创建ServerSocket对象
			s = ss.accept(); // 等待客户端连接
			os = new DataOutputStream(s.getOutputStream()); // 创建输出流
			is = new DataInputStream(s.getInputStream()); // 创建输入流
			recvThread.start(); // 启动接收数据的线程
		} catch (IOException e) {
		} finally {
			try {
				ss.close(); // 关闭ServerSocket
			} catch (IOException e) {
			}
		}
	}

	// 断开连接
	public void disconnect() {
		try {
			if (os != null)
				os.close(); // 关闭输出流
			if (is != null)
				is.close(); // 关闭输入流
			if (s != null)
				s.close(); // 关闭Socket
		} catch (IOException e) {
		}
		System.exit(0); // 退出程序
	}

	// 使用内部类创建接收数据线程
	private class RecvThread implements Runnable {
		public void run() {
			try {
				while (connected) { // 如果连接上了
					String str = is.readUTF(); // 接收客户端发送的数据
					contentTextArea.setText(contentTextArea.getText() + "client:" + str + '\n'); // 在文本区域显示接收到的数据
				}
			} catch (EOFException e) { // 客户端关闭了连接
				contentTextArea.setText("Client closed!");
			} catch (IOException e) {
				e.printStackTrace();
			}

		}
	}

	// 事件处理函数
	public void actionPerformed(ActionEvent e) {
		// 如果按下的是监听按钮
		if (e.getSource() == listenButton) {
			listenButton.setEnabled(false); // 禁用监听按钮
			start(); // 开始监听
		} else if (e.getSource() == closeButton) { // 如果按下的是关闭按钮
			disconnect(); // 断开连接
		} else if (e.getSource() == inputTextField) { // 如果按下的是输入框回车键
			String str = inputTextField.getText().trim(); // 获取输入框中的文本
			inputTextField.setText(""); // 清空输入框
			try {
				os.writeUTF(str); // 发送数据给客户端
				os.flush(); // 刷新输出流
				contentTextArea.setText(contentTextArea.getText() + "server:" + str + '\n'); // 在文本区域显示发送的数据
			} catch (IOException e1) {
			}
		}
	}

	// 主函数,创建窗口对象
	public static void main(String[] args) {
		new Server();
	}
}

客户端程序

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;

import javax.swing.*;

public class Client extends JFrame implements ActionListener {
	Socket s = null; // Socket对象
	DataOutputStream os = null; // 输出流
	DataInputStream is = null; // 输入流
	private boolean connected = false; // 是否连接标志
	JLabel ipLabel = new JLabel("IP"); // 显示IP地址的标签
	JTextField ipTextField = new JTextField("127.0.0.1"); // IP地址输入框
	JLabel portLabel = new JLabel("端口"); // 显示端口号的标签
	JTextField portTextField = new JTextField("8000"); // 端口号输入框
	JButton connectButton = new JButton("连接"); // 连接按钮
	JButton closeButton = new JButton("关闭"); // 关闭按钮
	JPanel panel = new JPanel(); // 包含各种控件的面板
	JTextField inputTextField = new JTextField(); // 输入框
	JTextArea contentTextArea = new JTextArea(); // 显示接收到的数据的文本区域
	Thread recvThread = new Thread(new RecvThread()); // 接收数据的线程

	// 构造函数
	public Client() {
		setTitle("客户端"); // 窗口标题
		setLocation(400, 300); // 窗口位置
		setSize(500, 500); // 窗口大小
		setLayout(new BorderLayout()); // 设置布局为边界布局
		panel.setLayout(new FlowLayout()); // 面板使用流式布局
		panel.add(ipLabel); // 添加IP地址标签到面板
		panel.add(ipTextField); // 添加IP地址输入框到面板
		panel.add(portLabel); // 添加端口号标签到面板
		panel.add(portTextField); // 添加端口号输入框到面板
		panel.add(connectButton); // 添加连接按钮到面板
		panel.add(closeButton); // 添加关闭按钮到面板
		add(panel, BorderLayout.NORTH); // 将面板添加到窗口北部
		add(new JScrollPane(contentTextArea), BorderLayout.CENTER); // 将文本区域添加到窗口中央,可以滚动
		add(inputTextField, BorderLayout.SOUTH); // 将输入框添加到窗口南部
		connectButton.addActionListener(this); // 连接按钮添加事件监听器
		closeButton.addActionListener(this); // 关闭按钮添加事件监听器
		inputTextField.addActionListener(this); // 输入框添加事件监听器

		addWindowListener(new WindowAdapter() { // 窗口关闭事件监听器,关闭程序时同时断开连接
			@Override
			public void windowClosing(WindowEvent e) {
				disconnect();
			}
		});
		setSize(500, 300); // 窗口大小
		setLocationRelativeTo(null); // 将窗口位于屏幕的中央
		setVisible(true); // 显示窗口
	}

	// 连接服务器
	public void connect() {
		try {
			String host, port;
			host = ipTextField.getText(); // 获取输入的IP地址
			port = portTextField.getText(); // 获取输入的端口号
			s = new Socket(host, Integer.parseInt(port)); // 创建Socket对象并连接服务器
			os = new DataOutputStream(s.getOutputStream()); // 创建输出流
			is = new DataInputStream(s.getInputStream()); // 创建输入流
			connected = true; // 标记已连接
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	// 断开连接
	public void disconnect() {
		try {
			if (os != null)
				os.close(); // 关闭输出流
			if (is != null)
				is.close(); // 关闭输入流
			if (s != null)
				s.close(); // 关闭Socket
		} catch (IOException e) {
		}
		System.exit(0); // 退出程序
	}

	// 使用内部类创建接收数据线程
	private class RecvThread implements Runnable {
		public void run() {
			try {
				while (connected) { // 如果连接上了
					String str = is.readUTF(); // 接收服务器发送的数据
					contentTextArea.setText(contentTextArea.getText() + "server:" + str + '\n'); // 在文本区域显示接收到的数据
				}
			} catch (EOFException e) { // 服务器关闭了连接
				contentTextArea.setText("Server closed!");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	// 事件处理函数
	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == connectButton) { // 如果按下的是连接按钮
			connectButton.setEnabled(false); // 禁用连接按钮
			connect(); // 连接服务器
			recvThread.start(); // 启动接收数据的线程
		} else if (e.getSource() == closeButton) { // 如果按下的是关闭按钮
			disconnect(); // 断开连接
		} else if (e.getSource() == inputTextField) { // 如果按下的是输入框回车键
			String str = inputTextField.getText().trim(); // 获取输入框中的文本
			inputTextField.setText(""); // 清空输入框
			try {
				os.writeUTF(str); // 发送数据给服务器
				os.flush(); // 刷新输出流
				contentTextArea.setText(contentTextArea.getText() + "client:" + str + '\n'); // 在文本区域显示发送的数据
			} catch (IOException e1) {
			}
		}
	}

	// 主函数,创建窗口对象
	public static void main(String[] args) {
		new Client();
	}
}

标签:Socket,输入框,add,添加,new,客户端,public,服务端,panel
From: https://www.cnblogs.com/whwh/p/17844480.html

相关文章

  • 前端升级客户端自动更新
    SPA类型应用,前端热发布后,用户端由于浏览器缓存不会重新获取index.html导致用户没有及时看到最新版本所以写了一个插件用户协助客户端实时更新//思路:对比每一个script中的src的地址有无变化因为打包后的js名称一般为test.dawe13s5.js中间8位为哈希值每次打包均不一样·......
  • oracle 轻量化包安装,使用第三方客户端
    轻量版客户端工具包:此方式适用于NavicatPremium、PLSQL、DBeaver等客户端工具的,如果其他程序(自己开发的程序,中间件等)要使用的话,还是要安装完整版得客户端。下载地址;64位客户端工具:https://download.oracle.com/otn_software/nt/instantclient/1912000/instantclient-basic-wind......
  • 将 OpenVP 客户端作为 Systemd 服务运行
    为了在服务器重新启动时自动建立连接,可以启用OpenVPN客户端systemd服务。在执行此操作之前,请将VPN配置文件的扩展名从更改.ovpn为.conf. 相应地替换文件名。cpkoromicha.ovpnkoromicha.conf将文件复制.conf到OpenVPN客户端配置目录/etc/openvpn/client.cpkoromicha.co......
  • 奇迹MU服务端:角色属性点计算公式
    奇迹MU各职业出生送点,可以说是每个搭建用户最直接也是最关心的问题,因为该点数涉及到角色的总点数,我们根据商业服务端的内容,给顾客一个参考公式,你可以根据这个参考公式,去计算你的角色在满级后可获得多少点数,以保障游戏的平衡。每个角色出身送点,都会有所倾斜,所以,我们以实际案例作为......
  • Netty源码学习4——服务端是处理新连接的&netty的reactor模式
    系列文章目录和关于我零丶引入在前面的源码学习中,梳理了服务端的启动,以及NioEventLoop事件循环的工作流程,并了解了Netty处理网络io重要的Channel,ChannelHandler,ChannelPipeline。这一篇将学习服务端是如何构建新的连接。一丶网络包接收流程当客户端发送的网络数据帧通过网......
  • INFINI Labs 产品更新 | 发布 Easysearch Java 客户端,Console 支持 SQL 查询等功能
    近年来,日志管理平台越来越流行。使用日志管理平台可以实时地、统一地、方便地管理和查看日志,挖掘日志数据价值,驱动运维、运营,提升服务管理效率。方案架构Beats是轻量级采集器,包括Filebeat、Metricbeat等。Easysearch是个分布式搜索引擎,提供搜集、分析、存储数据等主要功能。Con......
  • INFINI Labs 产品更新 | 发布 Easysearch Java 客户端,Console 支持 SQL 查询等功能
    近年来,日志管理平台越来越流行。使用日志管理平台可以实时地、统一地、方便地管理和查看日志,挖掘日志数据价值,驱动运维、运营,提升服务管理效率。方案架构Beats是轻量级采集器,包括Filebeat、Metricbeat等。Easysearch是个分布式搜索引擎,提供搜集、分析、存储数据等主要功......
  • 初识uds之abstract socket
    PS:要转载请注明出处,本人版权所有。PS:这个只是基于《我自己》的理解,如果和你的原则及想法相冲突,请谅解,勿喷。环境说明  无前言  在《记一次有趣的hwclock写RTC的PermissionDenied错误》(https://www.cnblogs.com/Iflyinsky/p/17841708.html或者https://https......
  • 基于Kiota生成API客户端
         Kiota是一个命令行工具,用于生成API客户端,以调用您感兴趣的任何OpenAPI描述的API。目标是消除您需要调用的每个API对不同的APISDK的依赖。KiotaAPI客户端提供了高质量APISDK提供的所有功能的强类型体验,但无需为每个HTTPAPI学习新类库。功能特点支持多种语言:C#、CLI......
  • 使用QT来写一个TCPsocket
    我们来了解一下什么是TCP的通讯小知识点,方便后续的理解1.TCP的简单了解由网上搜索的资料可知,tcp传输控制协议是一种面向连接的、可靠的、基于字节流的传输层通信协议。tcp通讯一定要经过三次握手才可以连接成功进行通讯;且,tcp通讯只能一对一进行连接;现在大多数通讯都是使用tcp......