using System; using System.Net; using System.Net.Sockets; using System.Reflection; using System.Reflection.Metadata; using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; public class Peer { private readonly TcpListener _listener; private string _targetIp = ""; private int _targetPort = 0; private int _port = 0; private string _name = ""; private bool running = true; private bool hasConnected = false; private bool userOnline = false; public Peer(int port, string targetIp, int targetPort, string name) { _listener = new TcpListener(IPAddress.Any, port); _port = port; _targetIp = targetIp; _targetPort = targetPort; _name = name; } public async Task Start(){ Task listen = StartListening(); Task chat = StartChat(); await Task.WhenAll(listen, chat); } private async Task StartListening(){ _listener.Start(); Console.WriteLine($"[info] Nasłuchuje na: 127.0.0.1:{_port}"); while(running){ try { TcpClient client = await _listener.AcceptTcpClientAsync(); _ = Task.Run(() => HandleClient(client)); } catch(Exception ex){ Console.WriteLine($"[błąd] Wystąpił nieoczekiwany błąd przy nasłuchiwaniu: {ex.Message}"); } } } private async Task HandleClient(TcpClient client) { try { using NetworkStream stream = client.GetStream(); using StreamReader reader = new(stream, Encoding.UTF8); while(running){ string? message = await reader.ReadLineAsync(); if(message == null) break; Content? contentData = JsonSerializer.Deserialize(message); if(contentData == null) break; ProcessMessage(contentData); } } catch(Exception ex){ Console.WriteLine(ex.Message); } } private void ProcessMessage(Content contentData){ try { ClearConsoleLine(); Console.SetCursorPosition(0, Console.CursorTop - 1); if(contentData.Message == "!exit"){ running = false; Console.WriteLine($"\n[info] Użytkownik {contentData.Sender} zakończył sesję"); } if(contentData.Message.Contains("dołączył/a do sesji") && !userOnline){ SendMessage($"jest online! Przywitaj się :D", false).Wait(); } if(contentData.ByUser){ Console.WriteLine($"\n[{contentData.SentAt}] {contentData.Sender}: {contentData.Message}"); } else { Console.WriteLine($"\n[info] [{contentData.SentAt}] Użytkownik {contentData.Sender} {contentData.Message}"); } Console.Write("> "); } catch (Exception ex) { Console.WriteLine(ex.Message); } } private async Task StartChat(){ while(running){ if(!hasConnected){ await SendMessage("dołączył/a do sesji", false); hasConnected = true; } ClearConsoleLine(); Console.SetCursorPosition(0, Console.CursorTop - 1); Console.Write("\n> "); string? message = Console.ReadLine(); if(message == "!exit"){ await SendMessage("!exit", false); await SendMessage("opuścił/a sesję", false); running = false; break; } else { await SendMessage(message ?? "", true); } } } private async Task SendMessage(string message, bool by_user){ try { TcpClient client = new (); await client.ConnectAsync(_targetIp, _targetPort); Content data = new() { Sender = _name, IpAddress = $"127.0.0.1:{_port}", Message = message, SentAt = DateTime.Now, ByUser = by_user }; string json = JsonSerializer.Serialize(data); using NetworkStream stream = client.GetStream(); using StreamWriter writer = new(stream, Encoding.UTF8) { AutoFlush = true }; await writer.WriteAsync(json); if(by_user){ ClearConsoleLine(); Console.SetCursorPosition(0, Console.CursorTop - 2); Console.WriteLine($"\n[{DateTime.Now}] Ja: {message}"); } } catch(Exception ex){ if(userOnline) Console.WriteLine($"[błąd] Nie udało się wysłać wiadomości: {ex.Message}"); } } void ClearConsoleLine(){ int cur = Console.CursorTop; Console.SetCursorPosition(0, Console.CursorTop); Console.Write(new string(' ', Console.WindowWidth)); Console.SetCursorPosition(0, cur); } } public class Content { public string Sender { get; set; } = ""; public string Message { get; set; } = ""; public string IpAddress { get; set; } = ""; public DateTime SentAt { get; set;} public bool ByUser { get; set; } }