diff --git a/Client/Client.csproj b/Client/Client.csproj
index 52ca3d7..5198609 100644
--- a/Client/Client.csproj
+++ b/Client/Client.csproj
@@ -1,19 +1,24 @@
-
- Exe
- net8.0
- enable
- true
- ChatRoom
- 聊天室
- ../Icon/favicon.ico
- true
-
+
+ Exe
+ net8.0
+ enable
+ enable
+ true
+ ChatRoom
+ 聊天室
+ ../Icon/favicon.ico
+ true
+
-
-
-
-
+
+ none
+
+
+
+
+
+
diff --git a/Client/Program.cs b/Client/Program.cs
index e26389e..34df003 100644
--- a/Client/Program.cs
+++ b/Client/Program.cs
@@ -8,15 +8,15 @@
namespace ChatRoom;
-internal class Client
+internal static class Client
{
- internal static string UserName { get; set; }
+ internal static string? UserName { get; set; }
private static async Task Main(string[] args)
{
- Option multiOption = new(name: "--multi", description: "允许重复运行实例。");
+ Option multiOption = new("--multi", "允许重复运行实例。");
RootCommand rootCommand = [multiOption];
- rootCommand.SetHandler(async (multi) =>
+ rootCommand.SetHandler(async multi =>
{
// 进程互斥
using Mutex _ = new(true, Assembly.GetExecutingAssembly().GetName().Name, out bool isNotRunning);
@@ -24,6 +24,7 @@ private static async Task Main(string[] args)
{
throw new EntryPointNotFoundException("你只能同时运行一个聊天室实例!");
}
+
await ChatMainAsync();
}, multiOption);
return await rootCommand.InvokeAsync(args);
@@ -39,7 +40,7 @@ private static async Task ChatMainAsync()
ILogger logger = factory.CreateLogger("聊天室");
Console.Title = "聊天室";
Socket client;
- string ip;
+ string? ip;
while (true)
{
client = new(SocketType.Stream, ProtocolType.Tcp);
@@ -47,20 +48,23 @@ private static async Task ChatMainAsync()
ip = Console.ReadLine();
try
{
- await client.ConnectAsync(IPAddress.TryParse(ip, out IPAddress address) ? address : IPAddress.Loopback, 19132);
+ await client.ConnectAsync(IPAddress.TryParse(ip, out IPAddress? address) ? address : IPAddress.Loopback,
+ 19132);
}
catch (SocketException ex)
{
logger.LogError("连接失败:{Message}", ex.Message);
continue;
}
+
break;
}
+
Console.Title = $"聊天室:{ip}";
Dictionary lastMessage = [];
int lastOne = 0;
Console.Clear();
- ThreadPool.QueueUserWorkItem(async (_) =>
+ _ = Task.Factory.StartNew(_ =>
{
while (true)
{
@@ -74,6 +78,7 @@ private static async Task ChatMainAsync()
{
continue;
}
+
BinaryReader reader = new(stream);
uuid = reader.ReadInt32();
ticks = reader.ReadInt64();
@@ -88,25 +93,32 @@ private static async Task ChatMainAsync()
client = new(SocketType.Stream, ProtocolType.Tcp);
try
{
- await client.ConnectAsync(IPAddress.TryParse(ip, out IPAddress address) ? address : IPAddress.Loopback, 19132);
+ client.ConnectAsync(
+ IPAddress.TryParse(ip, out IPAddress? address) ? address : IPAddress.Loopback,
+ 19132)
+ .Wait();
}
catch (SocketException)
{
}
}
+
logger.LogInformation("连接已恢复");
continue;
}
- if (lastMessage.TryGetValue(uuid, out string value) && value == message)
+
+ if (lastMessage.TryGetValue(uuid, out string? value) && value == message)
{
continue;
}
+
ConsoleColor temp = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Blue;
if (uuid != lastOne)
{
Console.Write($"{userName}({uuid}) ");
}
+
Console.WriteLine(new DateTime(ticks));
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.WriteLine(message);
@@ -114,15 +126,16 @@ private static async Task ChatMainAsync()
lastMessage[uuid] = message;
lastOne = uuid;
}
- });
+ }, TaskCreationOptions.LongRunning);
logger.LogInformation("连接已建立");
while (true)
{
- string line = Console.ReadLine();
+ string? line = Console.ReadLine();
if (string.IsNullOrEmpty(line) || !client.Connected)
{
continue;
}
+
if (line.StartsWith('/'))
{
try
@@ -133,16 +146,19 @@ private static async Task ChatMainAsync()
{
logger.LogError("命令运行失败:{Message}", ex.Message);
}
+
continue;
}
+
NetworkStream stream = new(client);
if (!stream.CanWrite)
{
continue;
}
+
BinaryWriter writer = new(stream);
writer.Write(line);
writer.Write(UserName ?? string.Empty);
}
}
-}
+}
\ No newline at end of file
diff --git a/Client/Utils/CommandHelper.cs b/Client/Utils/CommandHelper.cs
index 362a929..91bfb01 100644
--- a/Client/Utils/CommandHelper.cs
+++ b/Client/Utils/CommandHelper.cs
@@ -10,14 +10,14 @@ internal static class CommandHelper
Action = args =>
{
Dictionary commands = Commands;
- foreach (string arg in args)
+ foreach (Dictionary? subcommands in (from arg in args
+ where commands.ContainsKey(arg.ToUpper())
+ select commands[arg.ToUpper()].SubCommands)
+ .TakeWhile(subcommands => subcommands is not null))
{
- if ((!commands.ContainsKey(arg.ToUpper())) || (commands[arg.ToUpper()].SubCommands is null))
- {
- continue;
- }
- commands = commands[arg.ToUpper()].SubCommands;
+ commands = subcommands;
}
+
foreach ((string command, CommandData commandData) in commands)
{
Console.WriteLine($" {command.ToLower()}\t{commandData.Description}");
@@ -38,45 +38,60 @@ internal static class CommandHelper
{
throw new ArgumentException("参数数量错误");
}
+
Client.UserName = args[0];
}
}
}
}
};
+
internal static void Process(IList args, Dictionary commands, int deep = 1)
{
- string mainCommand = args[deep - 1].ToUpper();
- if (!commands.TryGetValue(mainCommand, out CommandData command))
- {
- throw new ArgumentException($"未知的命令:{args[deep - 1]}");
- }
- if (command.Action is not null)
+ while (true)
{
- List newArgs = new(args);
- if (args.Count - deep > 0)
+ string mainCommand = args[deep - 1].ToUpper();
+ if (!commands.TryGetValue(mainCommand, out CommandData command))
{
- newArgs.RemoveRange(0, deep);
+ throw new ArgumentException($"未知的命令:{args[deep - 1]}");
}
- command.Action(newArgs);
- }
- if (command.SubCommands is not null)
- {
- if (args.Count <= deep)
+
+ if (command.Action is not null)
{
- foreach ((string commandName, CommandData commandData) in command.SubCommands)
+ List newArgs = [..args];
+ if (args.Count - deep > 0)
{
- Console.WriteLine($" {commandName.ToLower()}\t{commandData.Description}");
+ newArgs.RemoveRange(0, deep);
}
- return;
+
+ command.Action(newArgs);
}
- Process(args, command.SubCommands, deep + 1);
+
+ if (command.SubCommands is not null)
+ {
+ if (args.Count <= deep)
+ {
+ foreach ((string commandName, CommandData commandData) in command.SubCommands)
+ {
+ Console.WriteLine($" {commandName.ToLower()}\t{commandData.Description}");
+ }
+
+ return;
+ }
+
+ commands = command.SubCommands;
+ ++deep;
+ continue;
+ }
+
+ break;
}
}
}
+
internal record struct CommandData
{
- public string Description { get; set; }
- public Action> Action { get; set; }
- public Dictionary SubCommands { get; set; }
-}
+ public string Description { get; init; }
+ public Action>? Action { get; init; }
+ public Dictionary? SubCommands { get; init; }
+}
\ No newline at end of file
diff --git a/Server/Program.cs b/Server/Program.cs
index c788100..8fee661 100644
--- a/Server/Program.cs
+++ b/Server/Program.cs
@@ -2,14 +2,14 @@
using System.Net.Sockets;
List clients = [];
-using Socket listenner = new(SocketType.Stream, ProtocolType.Tcp);
-listenner.Bind(new IPEndPoint(IPAddress.Any, 19132));
-listenner.Listen();
+using Socket listener = new(SocketType.Stream, ProtocolType.Tcp);
+listener.Bind(new IPEndPoint(IPAddress.Any, 19132));
+listener.Listen();
while (true)
{
- Socket client = await listenner.AcceptAsync();
+ Socket client = await listener.AcceptAsync();
clients.Add(client);
- ThreadPool.QueueUserWorkItem((_) =>
+ await Task.Factory.StartNew(_ =>
{
while (true)
{
@@ -21,6 +21,7 @@
{
continue;
}
+
BinaryReader reader = new(stream);
message = reader.ReadString();
userName = reader.ReadString();
@@ -30,6 +31,7 @@
clients.Remove(client);
return;
}
+
foreach (Socket otherClient in clients)
{
try
@@ -39,8 +41,25 @@
{
continue;
}
+
BinaryWriter writer = new(stream);
- writer.Write(client.RemoteEndPoint.ToString()[..client.RemoteEndPoint.ToString().LastIndexOf(':')].GetHashCode());
+ if (client.RemoteEndPoint is not null)
+ {
+ string? ip = client.RemoteEndPoint.ToString();
+ if (!string.IsNullOrWhiteSpace(ip))
+ {
+ writer.Write(ip[..ip.LastIndexOf(':')].GetHashCode());
+ }
+ else
+ {
+ writer.Write(Convert.ToInt32(client.Handle).ToString());
+ }
+ }
+ else
+ {
+ writer.Write(Convert.ToInt32(client.Handle).ToString());
+ }
+
writer.Write(DateTime.Now.Ticks);
writer.Write(message);
writer.Write(userName);
@@ -48,9 +67,8 @@
catch (IOException)
{
clients.Remove(client);
- continue;
}
}
}
- });
-}
+ }, TaskContinuationOptions.LongRunning);
+}
\ No newline at end of file
diff --git a/Server/Server.csproj b/Server/Server.csproj
index 1a99ace..678e8dc 100644
--- a/Server/Server.csproj
+++ b/Server/Server.csproj
@@ -1,13 +1,18 @@
-
- Exe
- net8.0
- enable
- true
- ChatRoom
- ChatRoom.$(MSBuildProjectName)
- true
-
+
+ Exe
+ net8.0
+ enable
+ enable
+ true
+ ChatRoom
+ ChatRoom.$(MSBuildProjectName)
+ true
+
+
+
+ none
+