Skip to content
This repository has been archived by the owner on Sep 16, 2024. It is now read-only.

Commit

Permalink
修复
Browse files Browse the repository at this point in the history
  • Loading branch information
Yushu2606 committed Jan 24, 2024
1 parent 04d2c5f commit 9ba84d0
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 72 deletions.
33 changes: 19 additions & 14 deletions Client/Client.csproj
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<PublishAot>true</PublishAot>
<RootNamespace>ChatRoom</RootNamespace>
<AssemblyName>聊天室</AssemblyName>
<ApplicationIcon>../Icon/favicon.ico</ApplicationIcon>
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
</PropertyGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PublishAot>true</PublishAot>
<RootNamespace>ChatRoom</RootNamespace>
<AssemblyName>聊天室</AssemblyName>
<ApplicationIcon>../Icon/favicon.ico</ApplicationIcon>
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
</ItemGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugType>none</DebugType>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0"/>
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1"/>
</ItemGroup>

</Project>
40 changes: 28 additions & 12 deletions Client/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,23 @@

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<int> Main(string[] args)
{
Option<bool> multiOption = new(name: "--multi", description: "允许重复运行实例。");
Option<bool> 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);
if (!isNotRunning && !multi)
{
throw new EntryPointNotFoundException("你只能同时运行一个聊天室实例!");
}
await ChatMainAsync();
}, multiOption);
return await rootCommand.InvokeAsync(args);
Expand All @@ -39,28 +40,31 @@ 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);
Console.Write("请输入服务器地址:");
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<int, string> lastMessage = [];
int lastOne = 0;
Console.Clear();
ThreadPool.QueueUserWorkItem(async (_) =>
_ = Task.Factory.StartNew(_ =>
{
while (true)
{
Expand All @@ -74,6 +78,7 @@ private static async Task ChatMainAsync()
{
continue;
}
BinaryReader reader = new(stream);
uuid = reader.ReadInt32();
ticks = reader.ReadInt64();
Expand All @@ -88,41 +93,49 @@ 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);
Console.ForegroundColor = temp;
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
Expand All @@ -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);
}
}
}
}
71 changes: 43 additions & 28 deletions Client/Utils/CommandHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ internal static class CommandHelper
Action = args =>
{
Dictionary<string, CommandData> commands = Commands;

Check warning on line 12 in Client/Utils/CommandHelper.cs

View workflow job for this annotation

GitHub Actions / build

Converting null literal or possible null value to non-nullable type.
foreach (string arg in args)
foreach (Dictionary<string, CommandData>? subcommands in (from arg in args
where commands.ContainsKey(arg.ToUpper())

Check warning on line 14 in Client/Utils/CommandHelper.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.
select commands[arg.ToUpper()].SubCommands)

Check warning on line 15 in Client/Utils/CommandHelper.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.
.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)

Check warning on line 21 in Client/Utils/CommandHelper.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.
{
Console.WriteLine($" {command.ToLower()}\t{commandData.Description}");
Expand All @@ -38,45 +38,60 @@ internal static class CommandHelper
{
throw new ArgumentException("参数数量错误");
}
Client.UserName = args[0];
}
}
}
}
};

internal static void Process(IList<string> args, Dictionary<string, CommandData> 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<string> 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<string> 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<List<string>> Action { get; set; }
public Dictionary<string, CommandData> SubCommands { get; set; }
}
public string Description { get; init; }
public Action<List<string>>? Action { get; init; }
public Dictionary<string, CommandData>? SubCommands { get; init; }
}
36 changes: 27 additions & 9 deletions Server/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
using System.Net.Sockets;

List<Socket> 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)
{
Expand All @@ -21,6 +21,7 @@
{
continue;
}
BinaryReader reader = new(stream);
message = reader.ReadString();
userName = reader.ReadString();
Expand All @@ -30,6 +31,7 @@
clients.Remove(client);
return;
}
foreach (Socket otherClient in clients)
{
try
Expand All @@ -39,18 +41,34 @@
{
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);
}
catch (IOException)
{
clients.Remove(client);
continue;
}
}
}
});
}
}, TaskContinuationOptions.LongRunning);
}
23 changes: 14 additions & 9 deletions Server/Server.csproj
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<PublishAot>true</PublishAot>
<RootNamespace>ChatRoom</RootNamespace>
<AssemblyName>ChatRoom.$(MSBuildProjectName)</AssemblyName>
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
</PropertyGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PublishAot>true</PublishAot>
<RootNamespace>ChatRoom</RootNamespace>
<AssemblyName>ChatRoom.$(MSBuildProjectName)</AssemblyName>
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugType>none</DebugType>
</PropertyGroup>

</Project>

0 comments on commit 9ba84d0

Please sign in to comment.