【Linux】【网络】不同子网下的客户端和服务器通信
【Linux】【网络】不同子网下的客户端和服务器通信
前两天在进行socket()网络编程并进行测试时,发现在不同wifi下两个电脑无法进行连接,大概去查找了如何解决 看到可以使用
frp 这个快速反向代理实现。
- frp 可让您将位于 NAT 或防火墙后面的本地服务器暴露到互联网。它目前支持TCP和UDP,以及HTTP和HTTPS协议,允许通过域名将请求转发到内部服务。
- github官网:https://github.com/fatedier/frp?tab=readme-ov-file#tcp-stream-multiplexing
先提一些基础概念,为什么在不同wifi下无法进行通信:
不同wifi下无法进行通信原因
1公网 IP与 内网 IP
IP地址是网络中的唯一标识符,用于区分网络中不同设备的位置。
- 公网 IP地址由互联网服务提供商(ISP)分配给用户,可以唯一地标识全球设备,以实现互联网上的通信。
- 内网 IP地址旨在用于组织内部网络,不会在全球互联网上路由,从而确保内部网络的安全。
1.1公网 IP
定义:公网 IP 是由互联网服务提供商(ISP)分配给你设备的 IP 地址,它是唯一的,且在互联网上是可以直接访问的。
作用:公网 IP 用于设备之间的通信,允许设备通过互联网相互访问。例如,当你访问一个网站时,浏览器会使用你的公网 IP 发送请求。
- 可以直接在互联网上被访问。
- 每个公网 IP 是唯一的,全球只有一个设备可以使用一个特定的公网 IP 地址。
- 公网 IP 的分配是有限的,IP 地址资源稀缺。
1.2 内网 IP
定义:内网 IP 是在局域网(LAN)内部使用的 IP 地址,它们不能在互联网上直接访问。内网设备可以通过 NAT(网络地址转换)技术与公网通信,但公网设备无法直接访问内网设备。
作用:内网 IP 用于局域网内设备之间的通信,通常由路由器通过 DHCP(动态主机配置协议)分配。
- 只能在局域网内使用,无法直接访问互联网。
- 由于内网 IP 地址的重复性,多个局域网可以使用相同的内网 IP 地址。
- 内网 IP地址范围是预定义的,常见的内网 IP 地址段有:
Class A:10.0.0.0 ~ 10.255.255.255
Class B:172.16.0.0 ~ 172.31.255.255
Class C:192.168.0.0 ~ 192.168.255.255
1.3区分公网 IP 和内网 IP
可以通过以下几个步骤来分辨一个 IP 地址是公网 IP 还是内网 IP:
-
a. 查看 IP 地址是否在内网地址范围内
内网 IP 地址有固定的地址段,如果某个 IP 地址属于以下任意一个范围,那么它就是内网 IP:
10.0.0.0 ~ 10.255.255.255 (Class A)
172.16.0.0 ~ 172.31.255.255 (Class B)
192.168.0.0 ~ 192.168.255.255 (Class C) -
b. 检查是否可通过外部访问
如果你能够直接访问某个 IP 地址并且该地址位于互联网,那么它是公网 IP。
内网 IP 地址只能在同一局域网内使用,无法通过互联网直接访问。
解决方案
拥有一台有公网IP的云服务器作为中转站,将局域网下的电脑将数据信息发送给中转的服务器,然后这个中转的服务器将收到的数据转给另外一台电脑,这样就可以实现两台电脑之间的互相通信。
原因:我们可以实现在局域网下的通信而不能在不是同一局域网下的通信是因为,不同的私网之间是无法通信的,我们使用的192.168.x.x都是私网,但是所有的私网却都可以和公网ip直接通信的。所以。想要在两个私网之间通信的话,我们就需要多一个步骤,也就是需要一个公网的IP作为中转站。

1云服务器
我的是阿里云服务器 当然只要是云服务器都可以

2 frp
2.1 云服务器上的配置
github下载frp网站:https://github.com/fatedier/frp/releases?page=5
因为我参考的文档使用的是0.33.0版本 我也就用了这个
ps:需要注意你的云服务器架构是什么
- ARM架构下arm版本
- x86_64架构选择amd 版本 我是这个版本的

可以使用命令下载:
wget https://github.com/fatedier/frp/releases/download/v0.33.0/frp_0.33.0_linux_amd64.tar.gz
然后解压缩:
tar xzvf frp_0.33.0_linux_amd64.tar.gz
将解压后的文件重命名:
mv frp_0.33.0_linux_amd64 frp
查看文件内容:
cd frp
ls
frp 默认给出两个服务端配置文件,一个是简版的 frps.ini,另一个是完整版本 frps_full.ini。我们这里通过简版的 frps.ini配置,快速的搭建起一个 frp服务端。
查看frps.ini的配置:
cat frps.ini
#输出
[common]
bind_port = 7000
由于默认配置中监听的是 7000 端口,但是用户可根据自己实际情况修改,我这里就没有修改了
启动frp服务端:
./frps -c ./frps.ini
输出:
root@iZ2vc4j4f5dy4g5cif3dnxZ:~/frp_set/frp# ./frps -c ./frps.ini
2025/02/20 14:13:02 [I] [service.go:178] frps tcp listen on 0.0.0.0:7000
2025/02/20 14:13:02 [I] [root.go:209] start frps success
2025/02/20 14:13:09 [I] [service.go:432] [e17730b293054812] client login info: ip [223.104.11.108:15309] version [0.33.0] hostname [] os [linux] arch [amd64]

2.2 云服务器上打开对应端口
可参考这个:https://blog.csdn.net/aa390481978/article/details/96837655


服务器配置
同样先下载,再解压,然后修改配置文件,之后启动
下载:
wget https://github.com/fatedier/frp/releases/download/v0.33.0/frp_0.33.0_linux_amd64.tar.gz
解压缩:
tar xzvf frp_0.33.0_linux_amd64.tar.gz
将解压后的文件重命名:
mv frp_0.33.0_linux_amd64 frp
修改查看frpc.ini的配置:
[common]
server_addr = your_server_ip # 公网服务器 IP 地址
server_port = 7000 # FRP 服务器端口[ssh]
type = tcp
local_ip = 192.168.x.x # 局域网电脑的 IP 地址
local_port = 23 # 局域网中要转发的服务端口(例如 SSH)
remote_port = 6001 # 在公网服务器上暴露的端口
server_addr是你服务器的公网ip

启动frp服务端:
./frpc -c ./frpc.ini
输出:
025/02/20 14:17:46 [I] [service.go:282] [c78168a348dd212e] login to server success, get run id [c78168a348dd212e], server udp port [0]
2025/02/20 14:17:46 [I] [proxy_manager.go:144] [c78168a348dd212e] proxy added: [ssh]
2025/02/20 14:17:46 [I] [control.go:179] [c78168a348dd212e] [ssh] start proxy success
客户端配置
同样先下载,再解压,然后修改配置文件,之后启动
下载:
wget https://github.com/fatedier/frp/releases/download/v0.33.0/frp_0.33.0_linux_amd64.tar.gz
解压缩:
tar xzvf frp_0.33.0_linux_amd64.tar.gz
将解压后的文件重命名:
mv frp_0.33.0_linux_amd64 frp
修改查看frpc.ini的配置:
[common]
server_addr = your_server_ip # 公网服务器 IP 地址
server_port = 7000 # FRP 服务器端口[ssh]
type = tcp
local_ip = 192.168.x.x # 局域网电脑的 IP 地址
local_port = 22 # 局域网中要转发的服务端口(例如 SSH)
remote_port = 6000 # 在公网服务器上暴露的端口
server_addr是你服务器的公网ip

启动frp服务端:
./frpc -c ./frpc.ini
输出:

注意事项
- 1 客户端和服务器的local_port = 22,remote_port = 6000 要设置为不一致的
- 2 客户端和服务器的名称也要设置为不一致的 ssh和ssh1
- 3 云服务器打开对应端口
ps:这边1,2设置为一致的是会导致 端口号 名称被占用的问题 但是按理说不应该 这边后续可以再试试
[W] [control.go:177] [0a1ee9193b4f3b0e] [ssh] start error: proxy name [ssh] is already in use
[W] [control.go:177] [0b9fe4453b7ae8ea] [ssh1] start error: port already used
3测试连接
配置完成后 测试客户端和服务器能否连接成功
下面是我的测试代码:
3.1 服务器
#include <iostream>
#include <cstring>
#include <unistd.h>
#include <arpa/inet.h>int main() {const char* host_ip = "192.168.xx.xx"; // A 局域网服务器的内网 IP 地址int host_port = 23; // 局域网服务端口// 创建 socketint server_socket = socket(AF_INET, SOCK_STREAM, 0);if (server_socket < 0) {std::cerr << "Socket creation failed!" << std::endl;return -1;}sockaddr_in server_address;server_address.sin_family = AF_INET;server_address.sin_port = htons(host_port);server_address.sin_addr.s_addr = inet_addr(host_ip);// 绑定并监听if (bind(server_socket, (sockaddr*)&server_address, sizeof(server_address)) < 0) {std::cerr << "Binding failed!" << std::endl;return -1;}if (listen(server_socket, 5) < 0) {std::cerr << "Listening failed!" << std::endl;return -1;}std::cout << "Server A is waiting for connections..." << std::endl;// 接受连接sockaddr_in client_address;socklen_t client_len = sizeof(client_address);int client_socket = accept(server_socket, (sockaddr*)&client_address, &client_len);if (client_socket < 0) {std::cerr << "Connection acceptance failed!" << std::endl;return -1;}std::cout << "Connection established with " << inet_ntoa(client_address.sin_addr) << std::endl;char buffer[1024];int bytes_received = recv(client_socket, buffer, sizeof(buffer), 0); // 接收数据if (bytes_received > 0) {buffer[bytes_received] = '\0';std::cout << "Received from client: " << buffer << std::endl;}const char* response = "Hello, Client B!";send(client_socket, response, strlen(response), 0); // 发送响应// 关闭连接close(client_socket);close(server_socket);return 0;
}
3.2 客户端
#include <iostream>
#include <cstring>
#include <unistd.h>
#include <arpa/inet.h>int main() {const char* server_ip = "xx.xx.xx.xx"; // 云服务器的公网 IPint server_port = 6001; // FRP 映射的端口// 创建 socketint client_socket = socket(AF_INET, SOCK_STREAM, 0);if (client_socket < 0) {std::cerr << "Socket creation failed!" << std::endl;return -1;}sockaddr_in server_address;server_address.sin_family = AF_INET;server_address.sin_port = htons(server_port);server_address.sin_addr.s_addr = inet_addr(server_ip);// 连接到服务器if (connect(client_socket, (sockaddr*)&server_address, sizeof(server_address)) < 0) {std::cerr << "Connection failed!" << std::endl;return -1;}const char* message = "Hello, Server A!";send(client_socket, message, strlen(message), 0); // 发送数据char buffer[1024];int bytes_received = recv(client_socket, buffer, sizeof(buffer), 0); // 接收数据if (bytes_received > 0) {buffer[bytes_received] = '\0';std::cout << "Received from server: " << buffer << std::endl;}// 关闭连接close(client_socket);return 0;
}
连接结果


注意事项
- 服务器绑定的端口是23 小于1024 要切换到管理员状态 否则会绑定失败

参考文章:
https://blog.csdn.net/weixin_44917390/article/details/106685219
https://blog.csdn.net/weixin_51354739/article/details/144422320
https://blog.csdn.net/qq_34623639/article/details/140506034
下个文章说一下frp具体是如何实现能够将客户端的连接准确转发给服务器的
相关文章:
【Linux】【网络】不同子网下的客户端和服务器通信
【Linux】【网络】不同子网下的客户端和服务器通信 前两天在进行socket()网络编程并进行测试时,发现在不同wifi下两个电脑无法进行连接,大概去查找了如何解决 看到可以使用 frp 这个快速反向代理实现。 frp 可让您将位于 NAT 或防火墙后面的本地服务器…...
SpringBoot教程(十四) SpringBoot之集成Redis
SpringBoot教程(十四) | SpringBoot之集成Redis 一、Redis集成简介二、集成步骤 2.1 添加依赖2.2 添加配置2.3 项目中使用之简单使用 (举例讲解)2.4 项目中使用之工具类封装 (正式用这个)2.5 序列化 &…...
DeepSeek掘金——VSCode 接入DeepSeek V3大模型,附使用说明
VSCode 接入DeepSeek V3大模型,附使用说明 由于近期 DeepSeek 使用人数激增,服务器压力较大,官网已 暂停充值入口 ,且接口响应也开始不稳定,建议使用第三方部署的 DeepSeek,如 硅基流动 或者使用其他模型/插件,如 豆包免费AI插件 MarsCode、阿里免费AI插件 TONGYI Lin…...
OpenHarmony分布式数据管理子系统
OpenHarmony分布式数据管理子系统 简介 目录 组件说明 分布式数据对象数据共享分布式数据服务Key-Value数据库首选项关系型数据库标准数据化通路 相关仓 简介 子系统介绍 分布式数据管理子系统支持单设备的各种结构化数据的持久化,以及跨设备之间数据的同步、…...
如何有效利用MYSQL的连接数
连接数配置2500~3000 依然发现连接不够用? -- 查看当前最大连接数 SHOW VARIABLES LIKE MAX_CONNECTIONS; -- 查看当前总链接数 SHOW STATUS LIKE Threads_connected; -- 查看当前进程明细 SHOW PROCESSLIST; 合理设置以下参数: 1. MySQL 的参数设置 …...
【Java学习】多态
面向对象系列三 一、方法相同 二、方法重写 1.概念 2.条件 三、向上转型 1.概念 2.方式 四、方法绑定 五、多态 一、方法相同 方法相同要求方法名相同、参数列表相同、返回值类型相同(与两方法修饰的访问限定符相不相同、静态非静态状态相不相同无关),而且…...
单片机 Bootloade与二进制文件的生成
单片机的 Bootloader 是一种特殊的程序,负责在单片机上电后初始化硬件、更新用户应用程序(固件),并将控制权移交给用户程序。以下是其运行机制和关键流程的详细说明: 1、单片机 Bootloader 的核心作用 固件更新&…...
MySQL数据库(3)—— 表操作
目录 一,创建表 1.1 创建表的SQL 1.2 演示 二,查看表 三,修改表 四,删除表 常用的表操作会涉及到两种SWL语句 DDL(Data Definition Language)数据定义语言:建表、改表、删表等࿰…...
Springboot + Ollama + IDEA + DeepSeek 搭建本地deepseek简单调用示例
1. 版本说明 springboot 版本 3.3.8 Java 版本 17 spring-ai 版本 1.0.0-M5 deepseek 模型 deepseek-r1:7b 需要注意一下Ollama的使用版本: 2. springboot项目搭建 可以集成在自己的项目里,也可以到 spring.io 生成一个项目 生成的话,如下…...
七星棋牌源码高阶技术指南:6端互通、200+子游戏玩法深度剖析与企业级搭建实战(完全开源)
在棋牌游戏行业高速发展的今天,如何构建一个具备高并发、强稳定性与多功能支持的棋牌游戏系统成为众多开发者和运营团队关注的焦点。七星棋牌全开源修复版源码 凭借其 六端互通、200子游戏玩法、多省区本地化支持,以及 乐豆系统、防沉迷、比赛场、AI智能…...
【深度学习在图像配准中的应用与挑战】
图像配准在深度学习中的解决方案越来越多,尤其是通过卷积神经网络(CNN)和生成对抗网络(GAN)等方法,可以显著提升图像配准的效果,尤其是在处理复杂的非刚性变换和大范围的图像差异时。 1. 基于深…...
HarmonyOS 开发套件 介绍 ——上篇
HarmonyOS 开发套件 介绍 ——上篇 在当今科技飞速发展的时代,操作系统作为智能设备的核心,其重要性不言而喻。而HarmonyOS,作为华为推出的全新操作系统,正以其独特的魅力和强大的功能,吸引着越来越多的开发者和用户的…...
跳跃游戏(力扣55)
题目问是否可以跳到数组最后一个下标,有的同学可能会思考如何模拟跳跃这个操作,但这是比较困难的,很容易把自己绕进去。可以换一种思路,我们不需要知道具体是如何跳到最后一个下标的,而是找到最大的跳跃范围。如果该跳…...
网络空间安全(1)web应用程序的发展历程
前言 Web应用程序的发展历程是一部技术创新与社会变革交织的长卷,从简单的文档共享系统到如今复杂、交互式、数据驱动的平台,经历了多个重要阶段。 一、起源与初期发展(1989-1995年) Web的诞生: 1989年,欧洲…...
机器学习 - 衡量模型的特性
最近我们陆续学习了机器学习的一些基础知识,本文来理解一下衡量机器学习模型的特性。了解机器学习模型的特性不仅有助于在理论上理解不同算法的工作原理,也能在实践中指导模型选择、参数调优、结果解释和系统部署,最终提高模型的实际应用效果…...
JUC并发—9.并发安全集合三
大纲 1.并发安全的数组列表CopyOnWriteArrayList 2.并发安全的链表队列ConcurrentLinkedQueue 3.并发编程中的阻塞队列概述 4.JUC的各种阻塞队列介绍 5.LinkedBlockingQueue的具体实现原理 6.基于两个队列实现的集群同步机制 1.并发安全的数组列表CopyOnWriteArrayList …...
Baklib云智协同:数字资产赋能企业效能跃升
内容概要 在数字化转型加速的背景下,Baklib通过构建智能化的知识中台架构,为企业打造了贯穿知识采集、整合、应用的全链路解决方案。该平台以动态知识图谱为核心技术底座,支持文档、音视频、代码等20余种格式的数字资产全生命周期管理&#…...
wordpress adrotate插件 文件上传漏洞
当你爆破进wordpress后台但权限不是管理员的时,如果你有adrotate插件操作权限可以用adrotate的文件上传功能get webshell 该漏洞需要AdRotate版本 < 5.13.3 第一步按顺序点击上传文件 在这里文件一定要压缩成zip格式,上传的时候也是上传这个zip 上…...
iframe 高さ 自動調整
iframeに異なるドメイン(クロスドメイン)のコンテンツを読み込んで高さを自動調節する方法 - みのるの備忘録 wordpress (親) 側の設定 <apex:iframe id"iframe" src"{!IF(isURL,Url, URLFOR($Resource.test))}" scrolling"…...
Apache Logic4j 库反序列化漏洞复现与深度剖析
前言 在渗透测试领域,反序列化漏洞一直是安全研究人员和攻击者关注的焦点。今天,我们将深入探讨 Apache Logic4j 库中的反序列化漏洞,详细了解其原理,并进行完整的复现演示。 一、漏洞原理 Apache Logic4j 库在处理对象的反序列…...
Python爬虫入门到精通:从零开始的数据采集之旅
一、网络世界的"小蜘蛛":什么是爬虫? 想象一下,你是一只勤劳的小蜘蛛,每天在互联网这张巨大的网上爬来爬去。你不需要自己织网,只需要顺着别人织好的网络路径,把有价值的信息收集到自己的小篮子里。这就是爬虫最形象的比喻——一个自动化的信息采集程序。 Py…...
《Operating System Concepts》阅读笔记:p50-p61
《Operating System Concepts》学习第 9 天,p50-p61 总结,总计 12 页。 一、技术总结 1.system call (1) 定义 The primary interface between processes and the operating system, providing a means to invoke services made available by the o…...
Transformer解析——(四)Decoder
本系列已完结,全部文章地址为: Transformer解析——(一)概述-CSDN博客 Transformer解析——(二)Attention注意力机制-CSDN博客 Transformer解析——(三)Encoder-CSDN博客 Transforme…...
Unity之Serialized序列化:从原理到实践
内容将会持续更新,有错误的地方欢迎指正,谢谢! Unity之Serialized序列化:从原理到实践 TechX 坚持将创新的科技带给世界! 拥有更好的学习体验 —— 不断努力,不断进步,不断探索 TechX —— 心探索、心…...
毕业项目推荐:基于yolov8/yolov5/yolo11的番茄成熟度检测识别系统(python+卷积神经网络)
文章目录 概要一、整体资源介绍技术要点功能展示:功能1 支持单张图片识别功能2 支持遍历文件夹识别功能3 支持识别视频文件功能4 支持摄像头识别功能5 支持结果文件导出(xls格式)功能6 支持切换检测到的目标查看 二、数据集三、算法介绍1. YO…...
Blaze RangePartitioning 算子Native实现全解析
引言:本文将全面且深入地解析Blaze RangePartitioning算子的Native实现过程。相较于原生Spark,RangePartitioning的Native实现在执行时间上达到了30%的显著下降,同时在资源开销方面节省了高达76%。这一改进大幅降低了运行成本,展现…...
么是静态住宅IP,跨境电商为什么需要静态住宅IP
静态住宅IP是指直接分配给一台属于私人住宅网络的设备的固定IP地址,这种地址不会频繁更改。它们作为代理IP,使使用者能够通过这些代理服务器进行网络访问,而对外显示的则是该住宅的IP地址。由于这些IP地址属于真实的住宅或个人,并…...
1、Window Android 13模拟器 将编译的映像文件导入Android Studio
1、环境准备 编译环境:Ubuntu-18.04.5编译版本:android13-release下载地址:清华大学开源软件镜像站AOSP # 下载repo # 同步代码:repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest -b android13-r…...
MTK-Android13-包安装器PackageInstaller 静默安装实现
目的 我们最终是为了搞明白安装的整个流程。一方面通过安卓系统自带的包安装器来了解PMS 安装流程;另一方面熟悉框架层Framework 针对Android apk 安装流程。 前两篇文章分析了PackagerInstaller 安装流程。 Android13-包安装器PackageInstaller-之apk安装跳转 An…...
基于ffmpeg+openGL ES实现的视频编辑工具-opengl相关逻辑(五)
在我们的项目中,OpenGL ES 扮演着至关重要的角色,其主要功能是获取图像数据,经过一系列修饰后将处理结果展示到屏幕上,以此实现各种丰富多样的视觉效果。为了让大家更好地理解后续知识,本文将详细介绍 OpenGL 相关代码。需要注意的是,当前方案将对 OpenGL 的所有操作都集…...
