-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Web chat #6
base: main
Are you sure you want to change the base?
Web chat #6
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
| ||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebChat", "WebChat\WebChat.csproj", "{26C3FA72-8E5F-42C8-BDB0-3BE8CF16BD14}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|Any CPU = Debug|Any CPU | ||
Release|Any CPU = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{26C3FA72-8E5F-42C8-BDB0-3BE8CF16BD14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{26C3FA72-8E5F-42C8-BDB0-3BE8CF16BD14}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{26C3FA72-8E5F-42C8-BDB0-3BE8CF16BD14}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{26C3FA72-8E5F-42C8-BDB0-3BE8CF16BD14}.Release|Any CPU.Build.0 = Release|Any CPU | ||
EndGlobalSection | ||
EndGlobal |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
namespace WebChat; | ||
|
||
using System.Net.Sockets; | ||
|
||
/// <summary> | ||
/// Chat client. | ||
/// </summary> | ||
public class Client : IDisposable | ||
{ | ||
private readonly TcpClient _client; | ||
|
||
private readonly NetworkStream _networkStream; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="Client"/> class. | ||
/// </summary> | ||
public Client(string host, int port) | ||
{ | ||
_client = new TcpClient(host, port); | ||
|
||
_networkStream = _client.GetStream(); | ||
} | ||
|
||
/// <summary> | ||
/// Gets a value indicating whether the client is disposed. | ||
/// </summary> | ||
public bool IsDisposed { get; private set; } | ||
|
||
/// <summary> | ||
/// Releases all resources used by the current instance of the <see cref="Client"/> class. | ||
/// </summary> | ||
public void Dispose() | ||
{ | ||
if (IsDisposed) | ||
{ | ||
return; | ||
} | ||
|
||
_networkStream.Dispose(); | ||
_client.Dispose(); | ||
|
||
IsDisposed = true; | ||
} | ||
|
||
/// <summary> | ||
/// Runs client. | ||
/// </summary> | ||
public async Task RunAsync() | ||
{ | ||
await Processing.ProcessQuery(_networkStream); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
namespace WebChat; | ||
|
||
using System.Net.Sockets; | ||
|
||
/// <summary> | ||
/// Class for processing get and post queries. | ||
/// </summary> | ||
public static class Processing | ||
{ | ||
/// <summary> | ||
/// Processes get and post queries. | ||
/// </summary> | ||
/// <param name="stream">Working stream.</param> | ||
public static async Task ProcessQuery(NetworkStream stream) | ||
{ | ||
await Task.Run(async () => await Post(stream)); | ||
await Task.Run(async () => await Get(stream)); | ||
Comment on lines
+16
to
+17
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Так мы сначала должны будем дождаться выполнения Post, а уже затем переходить к Get. Что не очень для чата. Надо было var task1 = Post(stream);
var task2 = Get(stream);
await task1;
await task2; Есть большая разница, когда делать await |
||
} | ||
|
||
private static async Task Post(NetworkStream stream) | ||
{ | ||
while (true) | ||
{ | ||
var writer = new StreamWriter(stream); | ||
var message = Console.ReadLine(); | ||
await writer.WriteAsync(message); | ||
await writer.FlushAsync(); | ||
await stream.FlushAsync(); | ||
|
||
writer = null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Бесполезно, всё равно его перетрёт тут же |
||
} | ||
} | ||
|
||
private static async Task Get(NetworkStream stream) | ||
{ | ||
while (true) | ||
{ | ||
var reader = new StreamReader(stream); | ||
var message = await reader.ReadLineAsync(); | ||
Console.WriteLine(message); | ||
|
||
reader = null; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
using WebChat; | ||
|
||
switch (args.Length) | ||
{ | ||
case 1: | ||
{ | ||
await StartServer(args); | ||
break; | ||
} | ||
|
||
case 2: | ||
{ | ||
await StartClient(args); | ||
break; | ||
} | ||
|
||
default: | ||
{ | ||
throw new ArgumentException(); | ||
} | ||
} | ||
|
||
async Task StartClient(string[] args) | ||
{ | ||
if (!int.TryParse(args[1], out var port)) | ||
{ | ||
throw new ArgumentException(); | ||
} | ||
|
||
using var client = new Client(args[0], port); | ||
await client.RunAsync(); | ||
} | ||
|
||
async Task StartServer(string[] args) | ||
{ | ||
if (!int.TryParse(args[0], out var port)) | ||
{ | ||
throw new ArgumentException(); | ||
} | ||
|
||
using var server = new Server(port); | ||
await server.RunAsync(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
namespace WebChat; | ||
|
||
using System.Net; | ||
using System.Net.Sockets; | ||
|
||
/// <summary> | ||
/// Chat server. | ||
/// </summary> | ||
public class Server : IDisposable | ||
{ | ||
private readonly TcpListener _listener; | ||
|
||
private readonly CancellationTokenSource _cts = new (); | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="Server"/> class. | ||
/// </summary> | ||
public Server(int port) | ||
{ | ||
_listener = new TcpListener(IPAddress.Any, port); | ||
} | ||
|
||
/// <summary> | ||
/// Gets a value indicating whether the server is disposed. | ||
/// </summary> | ||
public bool IsDisposed { get; private set; } | ||
|
||
private void Stop() => _cts.Cancel(); | ||
|
||
/// <summary> | ||
/// Releases all resources used by the current instance of the <see cref="Server"/> class. | ||
/// </summary> | ||
public void Dispose() | ||
{ | ||
if (IsDisposed) | ||
{ | ||
return; | ||
} | ||
|
||
if (!_cts.IsCancellationRequested) | ||
{ | ||
Stop(); | ||
} | ||
|
||
_cts.Dispose(); | ||
IsDisposed = true; | ||
} | ||
|
||
/// <summary> | ||
/// Runs server. | ||
/// </summary> | ||
public async Task RunAsync() | ||
{ | ||
_listener.Start(); | ||
|
||
try | ||
{ | ||
var token = _cts.Token; | ||
using var socket = await _listener.AcceptSocketAsync(token); | ||
await using var stream = new NetworkStream(socket); | ||
await Processing.ProcessQuery(stream); | ||
} | ||
finally | ||
{ | ||
_listener.Stop(); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>net6.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
</PropertyGroup> | ||
|
||
</Project> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Так TcpClient сразу начнёт подключаться к хосту, синхронно. Правильнее было создать TcpClient конструктором без параметров, а потом, уже в RunAsync, вызвать ConnectAsync.