ChatX/chatserver/Program.cs

264 lines
14 KiB
C#
Raw Permalink Normal View History

using System.Net.Sockets;
using System.Net.Http;
using log4net;
using log4net.Config;
using System.Net;
using System.Data.SQLite;
using chatserver.Data;
using System.Text.Json;
using System.Reflection;
[assembly: XmlConfigurator(ConfigFile = "config/log4net.config", Watch = true)]
namespace chatserver
{
internal class ChatServer
{
private static readonly ILog log = LogManager.GetLogger(typeof(ChatServer));
private static List<Socket> Client = new();
private static List<string> token = new();
private static Socket? Server;
private static SQLiteConnection? User_db;
static void Main(string[] args)
{
//XmlConfigurator.Configure();
log.Info("Hello World!");
Server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Server.Bind(new IPEndPoint(IPAddress.Any, 52006));
Server.Listen(20);
OpenUser_db();
log.Info("服务器以在52006端口监听");
while (true)
{
try
{
Socket client = Server.Accept();
Client.Add(client);
log.Info($"用户{client.RemoteEndPoint}连接");
Thread thread = new Thread(() => HandleClient(client));
thread.Start();
}
catch (Exception ex)
{
log.Error("Error accepting client connection: " + ex.Message);
}
}
}
public static void OpenUser_db()
{
log.Info("正在打开数据库连接...");
User_db = new SQLiteConnection("Data Source=ServerUser.db;Version=3;"); //没有数据库则自动创建
User_db.Open();
EnsureUsersTableExists(); // 确保users表存在
log.Info("数据库连接已打开");
}
static void HandleClient(Socket socket)
{
try
{
while (true)
{
byte[] buffer = new byte[1024];
int received = socket.Receive(buffer);
if (received == 0) break; // 客户端断开连接
string message = System.Text.Encoding.UTF8.GetString(buffer, 0, received);
log.Info("Received message: " + message);
var Type = JsonSerializer.Deserialize<TypeData>(message);
if (Type != null)
{
if (Type.type == "register")
{
var sginuser = JsonSerializer.Deserialize<SignData>(message);
if (sginuser != null && sginuser.username != null && sginuser.password != null)
{
log.Info($"用户 {sginuser.username} 正在注册");
if (string.IsNullOrEmpty(sginuser.username) || string.IsNullOrEmpty(sginuser.password))
{
log.Warn("用户名或密码不能为空");
var emptyResult = new SignResultData { type = "register", status = "error_-1", message = "用户名或密码不能为空" };
socket.Send(JsonSerializer.SerializeToUtf8Bytes(emptyResult));
continue; // 如果用户名或密码为空,则跳过注册流程
}
if (sginuser.username.Length < 2 || sginuser.username.Length > 20)
{
log.Warn($"用户注册时 {sginuser.username} 用户名长度不符合要求");
var lengthResult = new SignResultData { type = "register", status = "error_2", message = "用户名长度必须在2到20个字符之间" };
socket.Send(JsonSerializer.SerializeToUtf8Bytes(lengthResult));
continue; // 如果用户名长度不符合要求,则跳过注册流程
}
if (sginuser.password.Length < 4 || sginuser.password.Length > 20)
{
log.Warn($"用户注册时 {sginuser.username} 密码长度不符合要求");
var weakPwdResult = new SignResultData { type = "register", status = "error_1", message = "密码长度必须在4到20个字符之间" };
socket.Send(JsonSerializer.SerializeToUtf8Bytes(weakPwdResult));
continue; // 如果密码过弱,则跳过注册流程
}
if (UserExists(sginuser.username))
{
log.Warn($"用户 {sginuser.username} 已存在");
var Result = new SignResultData { type = "register", status = "error_0", message = "用户名已存在" };
socket.Send(System.Text.Encoding.UTF8.GetBytes(JsonSerializer.Serialize(Result)));
continue;// 如果用户名已存在,则跳过注册流程
}
var cmd = new SQLiteCommand("INSERT INTO users (userid, username, password) VALUES (@userid, @username, @password)", User_db);
var timedUlid = Ulid.NewUlid(DateTimeOffset.UtcNow);
cmd.Parameters.AddWithValue("@userid", timedUlid);
cmd.Parameters.AddWithValue("@username", sginuser.username);
cmd.Parameters.AddWithValue("@password", sginuser.password);
cmd.ExecuteNonQuery();
log.Info($"用户 {sginuser.username} 注册成功(id:{timedUlid})");
var result = new SignResultData { type = "register", status = "succeed", message = "注册成功" };
socket.Send(System.Text.Encoding.UTF8.GetBytes(JsonSerializer.Serialize(result)));
}
}
else if (Type.type == "login")
{
var loginData = JsonSerializer.Deserialize<LoginData>(message);
if (loginData != null)
{
if (string.IsNullOrEmpty(loginData.username) || string.IsNullOrEmpty(loginData.password))
{
log.Warn("用户名或密码不能为空");
var emptyResult = new LoginResultData { type = "login", status = "error_-1", message = "用户名或密码不能为空" };
socket.Send(JsonSerializer.SerializeToUtf8Bytes(emptyResult));
continue; // 如果用户名或密码为空,则跳过登录流程
}
if (loginData.username.Length < 2 || loginData.username.Length > 20)
{
log.Warn($"用户登录时 {loginData.username} 用户名长度不符合要求");
var lengthResult = new LoginResultData { type = "login", status = "error_2", message = "用户名长度必须在2到20个字符之间" };
socket.Send(JsonSerializer.SerializeToUtf8Bytes(lengthResult));
continue; // 如果用户名长度不符合要求,则跳过登录流程
}
var Authentication = UserAuthentication(loginData.username, loginData.password);
if (Authentication != "")
{
log.Info($"用户 {loginData.username} 登录成功 (id:{Authentication})");
var result = new LoginResultData
{
type = "login",
status = "succeed",
message = "登录成功",
//token = Authentication,
username = loginData.username,
userid = Authentication
};
socket.Send(System.Text.Encoding.UTF8.GetBytes(JsonSerializer.Serialize(result)));
}
else
{
log.Warn($"用户 {loginData.username} 登录失败,用户名或密码错误");
var result = new LoginResultData { type = "login", status = "error_0", message = "用户名或密码错误" };
socket.Send(System.Text.Encoding.UTF8.GetBytes(JsonSerializer.Serialize(result)));
}
}
}
else if (Type.type == "chat")
{
var chatData = JsonSerializer.Deserialize<ChatData>(message);
if (chatData != null && chatData.message != null)
{
log.Info($"接收到聊天消息: {chatData.message}");
var chatRegisterData = new ChatRegisterData
{
type = "chat",
userid = chatData.userid ?? "Unid",
user = GetUsernameByUserId(chatData.userid!),
message = chatData.message,
msgtype = chatData.msgtype ?? MessageType.Text,
// 替换为
timestamp = DateTime.Now
};
foreach (var client in Client)
{
client.Send(System.Text.Encoding.UTF8.GetBytes(JsonSerializer.Serialize(chatRegisterData)));
}
}
else
{
log.Warn("接收到无效的聊天消息");
}
}
else
{
log.Warn("未知的请求类型: " + Type.type);
}
}
}
}
catch (SocketException ex)
{
log.Error("Socket error: " + ex.Message);
}
catch (JsonException ex)
{
log.Error("JSON parsing error: " + ex.Message);
}
catch (Exception ex)
{
log.Error("Error handling client: " + ex.Message);
}
finally
{
log.Info($"用户{socket.RemoteEndPoint}已断开连接");
socket.Close();
Client.Remove(socket);
}
}
/// <summary>
/// 查询User_db是否有相同用户名
/// </summary>
/// <param name="username"></param>
/// <returns></returns>
static bool UserExists(string username)
{
using var cmd = new SQLiteCommand("SELECT COUNT(*) FROM users WHERE username = @username", User_db);
cmd.Parameters.AddWithValue("@username", username);
var count = Convert.ToInt32(cmd.ExecuteScalar());
return count > 0;
}
/// <summary>
/// 验证用户登录信息并返回userid结果
/// </summary>
/// <param name="username"></param>
/// <param name="password"></param>
/// <returns></returns>
static string UserAuthentication(string username, string password)
{
using var cmd = new SQLiteCommand("SELECT userid FROM users WHERE username = @username AND password = @password", User_db);
cmd.Parameters.AddWithValue("@username", username);
cmd.Parameters.AddWithValue("@password", password);
var result = cmd.ExecuteScalar();
return result != null ? result.ToString()! : string.Empty;
}
// 在ChatServer类中添加一个方法用于初始化users表
private static void EnsureUsersTableExists()
{
using var cmd = new SQLiteCommand(@"
CREATE TABLE IF NOT EXISTS users (
userid TEXT PRIMARY KEY,
username TEXT NOT NULL UNIQUE,
password TEXT NOT NULL
)", User_db);
cmd.ExecuteNonQuery();
}
/// <summary>
/// 根据userid查询对应的用户名
/// </summary>
/// <param name="userid"></param>
/// <returns>用户名,如果不存在则返回</returns>
static string GetUsernameByUserId(string userid)
{
if (string.IsNullOrEmpty(userid) || userid == "Unid")
{
return "Unnamed"; // 如果userid为空或为"Unid",返回默认用户名
}
using var cmd = new SQLiteCommand("SELECT username FROM users WHERE userid = @userid", User_db);
cmd.Parameters.AddWithValue("@userid", userid);
var result = cmd.ExecuteScalar();
return result != null ? result.ToString()! : "Unnamed";
}
}
}