一个近乎完美的解决方案
背景:需要一台20兆左右宽带的服务器,但是阿里云的云服务器太贵,如果带宽高的话,就更贵了。但是直接用本地的服务器,没有企业的公网固定ip,只有动态公网IP,只能ddns解决,但是ddns非企业的ttl时长最短也需要10分钟,ttl就是域名解析结果(ip地址)在运营商dns上保存的时长。如果这更新后的10分钟有用户通过域名访问,就会被运营商的dns导向一个不存在服务器的ip地址。真实ip无法及时更新。访问不到服务器。
没有企业,因此需要一个廉价的解决方案
↓↓↓
需要准备:阿里云ecs实例一个(勾选阿里云分配公网ip),本地网络是公网ip,阿里云域名一个(方便后续升级,防止解析服务器ip变化,用来解析aliyunecs,没有的话用阿里云ecs的ip直接访问也行,但是不安全)
实现方法:在本地服务器搭建真正的数据库,所有的东西都运行在本地服务器,再额外编写一个获取本机ip的程序,并通过ajax上传到阿里云,每隔1秒检测一次,如果变化,就上传到阿里云ecs。
1-1.实时获取本机IP并打印在浏览器页面的方法(JavaScript需要浏览器打开webrtc)
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1>实时本机IP地址</h1>
<p id="ip"></p >
<script>
function getLocalIP(callback) {
const RTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection || window.mozRTCPeerConnection;
const rtc = new RTCPeerConnection({iceServers: []});
const noop = function(){};
rtc.createDataChannel('');
rtc.createOffer(function(sessionDescription) {
rtc.setLocalDescription(sessionDescription, noop, noop);
}, noop);
rtc.onicecandidate = function(event) {
if (event.candidate) {
const ipRegex = /\b(?:\d{1,3}\.){3}\d{1,3}\b/;
const match = ipRegex.exec(event.candidate.candidate);
const localIP = match ? match[0] : 'unknown';
callback(localIP);
rtc.onicecandidate = noop;
}
};
}
setInterval(function() {
getLocalIP(function(localIP) {
document.getElementById("ip").innerHTML = "Local IP Address: " + localIP;
});
}, 1000); // 更新频率(以毫秒为单位)
</script>
</body>
</html>
1-2.实时获取本地IP并上传(JavaScript+html实现)
//以下是使用普通JavaScript实现的前端代码示例,与下述Java服务器进行交互并存储和替换字符串:
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>String Storage Client</title>
</head>
<body>
<h1>String Storage Client</h1>
<div id="status"></div>
<label for="password">Access Password:</label>
<input type="password" id="password">
<br>
<label for="newString">New String:</label>
<input type="text" id="newString">
<br><br>
<button onclick="getStoreString()">Get Stored String</button>
<br><br>
<button onclick="updateString()">Update String</button>
<script>
const serverUrl = "http://localhost:8080";
function sendHttpRequest(url, method, data, successCallback, errorCallback) {
const xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
successCallback(xhr.responseText);
} else {
errorCallback(xhr.responseText);
}
}
};
xhr.send(data);
}
function getStoreString() {
const password = document.getElementById("password").value;
sendHttpRequest(serverUrl, "POST", password, function(response) {
document.getElementById("status").textContent = "Stored String: " + response;
}, function(error) {
document.getElementById("status").textContent = "Error: " + error;
});
}
function updateString() {
const password = document.getElementById("password").value;
const newString = document.getElementById("newString").value;
const requestData = password + "\n" + newString;
sendHttpRequest(serverUrl, "POST", requestData, function(response) {
document.getElementById("status").textContent = "Update Successful: " + response;
}, function(error) {
document.getElementById("status").textContent = "Error: " + error;
});
}
</script>
</body>
</html>
//这个前端代码使用了普通的JavaScript来发送XMLHttpRequest请求与
//服务器进行交互。页面中有两个输入框,一个用于输入访问密码,另
//一个用于输入新的字符串。点击"Get Stored String"按钮将发送密码
//给服务器进行校验,并将服务器返回的存储的字符串显示在页面上。
//点击"Update String"按钮将同时发送密码和新字符串给服务器,用于替换服务器中存储的字符串。
//请确保将`serverUrl`变量根据实际服务器的地址进行修改,以确保与Java服务器的URL地址匹配。
1-3云服务器端监听真实服务器发来的真实IP(Java实现)
以下是一个使用Java编写的示例服务器,可以存储前端发来的字符串并校验访问密码,以后前端再发送该字符串,就替换服务器里存储的这个字符串:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class StringStorageServer {
private static final int PORT = 8080;
private static final String ACCESS_PASSWORD = "password";
private static String storedString = "initial_string";
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
System.out.println("Server started, waiting for client connection...");
while (true) {
Socket clientSocket = serverSocket.accept();
System.out.println("Client connected from: " + clientSocket.getInetAddress());
PrintWriter writer = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
// Check access password
String requestPassword = reader.readLine();
if (!ACCESS_PASSWORD.equals(requestPassword)) {
System.out.println("Access password incorrect!");
writer.println("Access password incorrect!");
clientSocket.close();
continue;
}
// Send current stored string to client
writer.println(storedString);
// Receive and store new string from client
String newString = reader.readLine();
if (newString != null && !newString.trim().isEmpty()) {
storedString = newString;
System.out.println("New string received: " + storedString);
writer.println("String stored successfully.");
} else {
writer.println("Empty string received.");
}
clientSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
//这个服务器会监听8080端口,等待客户端连接。客户端会发送两行信息,第一行是访问密码,
//第二行是字符串。服务器会对密码进行校验,如果密码错误则返回错误信息并断开连接,
//否则将存储的字符串进行处理和存储,然后返回相应的信息。
//请记住,这只是一个简单的示例服务器,没有进行安全校验和错误处理。在实际生产环境中,
//还需要添加适当的安全措施和错误处理机制。
//请确保将`serverUrl`变量根据实际服务器的地址进行修改,以确保与Java服务器的URL地址
//匹配。
阿里云esc只搭建一个接收并保存这个字符串的后端程序。如果发来新的就替换这个字符串
结果:用户打开程序先通过域名访问,该域名会被导向阿里云ecs这个云服务器,该服务器会返回真实的服务器ip地址,此时用户就可以与真实ip的服务器建立联系。此后用户每打开一个新页面,重复上述操作(通过域名先访问
获得ip,然后按照这个ip加载资源),用的url地址都是这个ip对应的字符串