心跳封包
This commit is contained in:
parent
4d02d56152
commit
c623bbe26d
@ -1,39 +1,132 @@
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Text.Json; // 適用於 .NET Core 3.0+ / .NET 5/6/7/8
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Timers;
|
||||
namespace HeartbeatSender{
|
||||
|
||||
namespace HeartbeatSender
|
||||
{
|
||||
|
||||
public class HeartbeatData
|
||||
{
|
||||
public string branch_name { get; set; }
|
||||
public string room_name { get; set; }
|
||||
public string room_ip { get; set; }
|
||||
public string email { get; set; }
|
||||
public string password { get; set; }
|
||||
}
|
||||
public class heartbeatSender
|
||||
{
|
||||
private readonly UdpClient udpClient;
|
||||
private readonly IPEndPoint remoteEndPoint;
|
||||
private readonly System.Timers.Timer heartbeatTimer;
|
||||
public IPEndPoint RemoteEndPoint => remoteEndPoint;
|
||||
public heartbeatSender(string targetIp, int targetPort, int intervalMilliseconds = 3000)
|
||||
private readonly HttpClient httpClient = new HttpClient();
|
||||
private string token;
|
||||
private string heartbeatUrl;
|
||||
|
||||
public heartbeatSender(string heartbeatUrl)
|
||||
{
|
||||
udpClient = new UdpClient();
|
||||
// 設置 IP 和 PORT
|
||||
remoteEndPoint = new IPEndPoint(IPAddress.Parse(targetIp), targetPort);
|
||||
// 每3秒發送一次
|
||||
heartbeatTimer = new System.Timers.Timer(intervalMilliseconds);
|
||||
heartbeatTimer.Elapsed += SendHeartbeat;
|
||||
heartbeatTimer.AutoReset = true;
|
||||
this.heartbeatUrl = heartbeatUrl;
|
||||
}
|
||||
private void SendHeartbeat(object sender, ElapsedEventArgs e)
|
||||
public static string GetLocalIPv4()
|
||||
{
|
||||
foreach (var ip in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
|
||||
{
|
||||
if (ip.AddressFamily == AddressFamily.InterNetwork && !IPAddress.IsLoopback(ip))
|
||||
{
|
||||
return ip.ToString();
|
||||
}
|
||||
}
|
||||
return "127.0.0.1"; // fallback
|
||||
}
|
||||
public async Task<bool> LoginAndGetTokenAsync()
|
||||
{
|
||||
var loginUrl = "http://zqd.superstar.dnsnet.cc/api/room/receiveRegister";
|
||||
string hostName = System.Net.Dns.GetHostName();
|
||||
|
||||
var loginPayload = new
|
||||
{
|
||||
branch_name = "測試",
|
||||
room_name = "PC" + hostName.Substring(Math.Max(0, hostName.Length - 3)),
|
||||
room_ip = GetLocalIPv4(),
|
||||
email = "MachineKTV@gmail.com",
|
||||
password = "aa147258-"
|
||||
};
|
||||
|
||||
var json = JsonSerializer.Serialize(loginPayload);
|
||||
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
||||
|
||||
try
|
||||
{
|
||||
string heartbeatMessage = "HEARTBEAT";
|
||||
byte[] data = Encoding.UTF8.GetBytes(heartbeatMessage);
|
||||
udpClient.Send(data, data.Length, remoteEndPoint);
|
||||
Console.WriteLine($"Heartbeat sent to {remoteEndPoint.Address}:{remoteEndPoint.Port}");
|
||||
var response = await httpClient.PostAsync(loginUrl, content);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var responseJson = await response.Content.ReadAsStringAsync();
|
||||
// Console.WriteLine("API 回傳內容:" + responseJson);
|
||||
|
||||
using var doc = JsonDocument.Parse(responseJson);
|
||||
if (doc.RootElement.TryGetProperty("data", out JsonElement dataElement) &&
|
||||
dataElement.ValueKind == JsonValueKind.Object)
|
||||
{
|
||||
if (dataElement.TryGetProperty("token", out JsonElement tokenElement))
|
||||
{
|
||||
token = tokenElement.GetString();
|
||||
}
|
||||
}
|
||||
// Console.WriteLine("登入成功,取得 token:" + token);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error sending heartbeat: {ex.Message}");
|
||||
Console.WriteLine($"登入失敗:{ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public void Start() => heartbeatTimer.Start();
|
||||
public void Stop() => heartbeatTimer.Stop();
|
||||
|
||||
public async Task SendHeartbeatAsync()
|
||||
{
|
||||
if (string.IsNullOrEmpty(token))
|
||||
{
|
||||
Console.WriteLine("請先登入取得 token");
|
||||
return;
|
||||
}
|
||||
//Console.WriteLine(GetLocalIPv4());
|
||||
string hostName = System.Net.Dns.GetHostName();
|
||||
|
||||
var heartbeatData = new
|
||||
{
|
||||
branch_name = "測試",
|
||||
hostname = "PC" + hostName.Substring(Math.Max(0, hostName.Length - 3)),
|
||||
ip = GetLocalIPv4(),
|
||||
};
|
||||
|
||||
var json = JsonSerializer.Serialize(heartbeatData);
|
||||
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
||||
heartbeatUrl = "http://zqd.superstar.dnsnet.cc/api/room/heartbeat";
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, heartbeatUrl);
|
||||
request.Content = content;
|
||||
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
|
||||
// Console.WriteLine("送出的 JSON:");
|
||||
// Console.WriteLine(json);
|
||||
var response = await httpClient.SendAsync(request);
|
||||
try
|
||||
{
|
||||
|
||||
// Console.WriteLine($"心跳送出狀態:{response.StatusCode}");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var responseJson = await response.Content.ReadAsStringAsync();
|
||||
|
||||
using var doc = JsonDocument.Parse(responseJson);
|
||||
// Console.WriteLine("API 回傳內容:" + responseJson);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var errorContent = await response.Content.ReadAsStringAsync();
|
||||
Console.WriteLine($"送出心跳錯誤:{ex.Message}");
|
||||
Console.WriteLine($"後端回應內容:{errorContent}");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -6,14 +6,50 @@ using System.Diagnostics;
|
||||
namespace DualScreenDemo{
|
||||
public partial class PrimaryForm
|
||||
{
|
||||
private static string connectionStringfortest = "";
|
||||
public static void LoadConnectionStringFromFile(string filePath)
|
||||
{
|
||||
filePath = Path.Combine(Application.StartupPath, "txt", filePath);
|
||||
try
|
||||
{
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
string fileContent = File.ReadAllText(filePath).Trim();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(fileContent))
|
||||
{
|
||||
connectionStringfortest = fileContent;
|
||||
Console.WriteLine("連線字串載入成功。");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("檔案內容為空。");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("找不到指定的檔案:" + filePath);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("讀取檔案時發生錯誤:" + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetConnectionString()
|
||||
{
|
||||
return connectionStringfortest;
|
||||
}
|
||||
|
||||
public bool isLoggedIn = false;
|
||||
public string userPhone = string.Empty;
|
||||
public List<SongData> SearchSongs_Mysql(string query)
|
||||
{
|
||||
List<SongData> searchResults = new List<SongData>();
|
||||
Console.WriteLine(query);
|
||||
string connectionString = "Server=192.168.11.4;Port=3306;Database=Karaoke-Kingpin;User=Karaoke-Kingpin;Password=ESM7yTPMnavFmbBH;";
|
||||
|
||||
//string connectionString = "Server=192.168.11.4;Port=3306;Database=Karaoke-Kingpin;User=Karaoke-Kingpin;Password=ESM7yTPMnavFmbBH;";
|
||||
string connectionString = GetConnectionString();
|
||||
using (var connection = new MySqlConnection(connectionString))
|
||||
{
|
||||
Stopwatch stopwatch = new Stopwatch();
|
||||
@ -65,8 +101,8 @@ namespace DualScreenDemo{
|
||||
public static List<Artist> SearchSingers_Mysql(string query){
|
||||
List<Artist> searchResults = new List<Artist>();
|
||||
Console.WriteLine(query);
|
||||
string connectionString = "Server=192.168.11.4;Port=3306;Database=Karaoke-Kingpin;User=Karaoke-Kingpin;Password=ESM7yTPMnavFmbBH;";
|
||||
|
||||
//string connectionString = "Server=192.168.11.4;Port=3306;Database=Karaoke-Kingpin;User=Karaoke-Kingpin;Password=ESM7yTPMnavFmbBH;";
|
||||
string connectionString = GetConnectionString();
|
||||
using (var connection = new MySqlConnection(connectionString))
|
||||
{
|
||||
Stopwatch stopwatch = new Stopwatch();
|
||||
@ -100,8 +136,8 @@ namespace DualScreenDemo{
|
||||
|
||||
string query = $"INSERT INTO FavoriteSongs (userPhone,songNumber) VALUES ('{userPhone}','{songNumber}');";
|
||||
Console.WriteLine(query);
|
||||
string connectionString = "Server=192.168.11.4;Port=3306;Database=Karaoke-Kingpin;User=Karaoke-Kingpin;Password=ESM7yTPMnavFmbBH;";
|
||||
|
||||
//string connectionString = "Server=192.168.11.4;Port=3306;Database=Karaoke-Kingpin;User=Karaoke-Kingpin;Password=ESM7yTPMnavFmbBH;";
|
||||
string connectionString = GetConnectionString();
|
||||
using (var connection = new MySqlConnection(connectionString))
|
||||
{
|
||||
|
||||
@ -128,8 +164,8 @@ namespace DualScreenDemo{
|
||||
string songlist = phonenumber + "的歌單";
|
||||
string query = $"INSERT INTO FavoriteSongs (userPhone,songNumber) VALUES ('{phonenumber}','{songlist}');";
|
||||
Console.WriteLine(query);
|
||||
string connectionString = "Server=192.168.11.4;Port=3306;Database=Karaoke-Kingpin;User=Karaoke-Kingpin;Password=ESM7yTPMnavFmbBH;";
|
||||
|
||||
//string connectionString = "Server=192.168.11.4;Port=3306;Database=Karaoke-Kingpin;User=Karaoke-Kingpin;Password=ESM7yTPMnavFmbBH;";
|
||||
string connectionString = GetConnectionString();
|
||||
using (var connection = new MySqlConnection(connectionString))
|
||||
{
|
||||
|
||||
@ -163,7 +199,8 @@ namespace DualScreenDemo{
|
||||
|
||||
}
|
||||
public bool checkPhoneNumberExist(string phonenumber){
|
||||
string connectionString = "Server=192.168.11.4;Port=3306;Database=Karaoke-Kingpin;User=Karaoke-Kingpin;Password=ESM7yTPMnavFmbBH;";
|
||||
//string connectionString = "Server=192.168.11.4;Port=3306;Database=Karaoke-Kingpin;User=Karaoke-Kingpin;Password=ESM7yTPMnavFmbBH;";
|
||||
string connectionString = GetConnectionString();
|
||||
bool exists = false;
|
||||
using (var connection = new MySqlConnection(connectionString))
|
||||
{
|
||||
@ -212,8 +249,8 @@ namespace DualScreenDemo{
|
||||
public void AddSongCount(string id){
|
||||
string query = $"UPDATE songs SET song_counts = song_counts+1 WHERE id = '{id}';";
|
||||
Console.WriteLine(query);
|
||||
string connectionString = "Server=192.168.11.4;Port=3306;Database=Karaoke-Kingpin;User=Karaoke-Kingpin;Password=ESM7yTPMnavFmbBH;";
|
||||
|
||||
//string connectionString = "Server=192.168.11.4;Port=3306;Database=Karaoke-Kingpin;User=Karaoke-Kingpin;Password=ESM7yTPMnavFmbBH;";
|
||||
string connectionString = GetConnectionString();
|
||||
using (var connection = new MySqlConnection(connectionString))
|
||||
{
|
||||
|
||||
|
@ -239,6 +239,7 @@ namespace DualScreenDemo
|
||||
multiPagePanel.PageIndexChanged += HandlePageChanged;
|
||||
// 添加 Load 事件處理
|
||||
this.Load += PrimaryForm_Load;
|
||||
LoadConnectionStringFromFile("test.env");
|
||||
|
||||
}
|
||||
|
||||
|
32
Program.cs
32
Program.cs
@ -2,6 +2,7 @@ using System.IO;
|
||||
using Microsoft.Win32;
|
||||
using System.Diagnostics;
|
||||
using DBObj;
|
||||
using HeartbeatSender;
|
||||
|
||||
namespace DualScreenDemo
|
||||
{
|
||||
@ -14,8 +15,33 @@ namespace DualScreenDemo
|
||||
private static PrimaryForm primaryForm; // 儲存實例的參考
|
||||
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
var sender = new HeartbeatSender.heartbeatSender("http://zqd.superstar.dnsnet.cc/api/room/receiveRegister");
|
||||
|
||||
// 同步呼叫非同步登入取得 token
|
||||
bool loginSuccess = sender.LoginAndGetTokenAsync().GetAwaiter().GetResult();
|
||||
|
||||
if (loginSuccess)
|
||||
{
|
||||
// 先送一次心跳 (同步呼叫)
|
||||
sender.SendHeartbeatAsync().GetAwaiter().GetResult();
|
||||
|
||||
// 背景持續每3秒送心跳
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
await sender.SendHeartbeatAsync();
|
||||
await Task.Delay(3000); // 每3秒送一次
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("登入失敗,無法送出心跳");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// COM 初始化
|
||||
@ -58,7 +84,7 @@ static void Main()
|
||||
primaryForm.Size = new Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
|
||||
|
||||
// 在完整初始化後檢查狀態
|
||||
string stateFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"txt","states.txt");
|
||||
string stateFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "txt", "states.txt");
|
||||
bool isClosedState = File.Exists(stateFilePath) &&
|
||||
File.ReadAllText(stateFilePath).Trim().Equals("CLOSE", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
|
@ -176,9 +176,6 @@
|
||||
<Compile Update="PrimaryFormParts\SingerSearch\PrimaryForm.SingerSearch.PinyinSearch.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Update="PrimaryFormParts\SingerSearch\PrimaryForm.SingerSearch.StrokeCountSearch.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Update="PrimaryFormParts\SingerSearch\PrimaryForm.SingerSearch.WordCountSearch.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
|
Loading…
x
Reference in New Issue
Block a user