Problem z kodem C#: konsolowy chat

0

Witam
Napisałem prosty chat przy użyciu C#. Problemem jest fakt, że każdą wiadomość trzeba "popchnąć" za pomocą entera tak, aby możnabyło otrzymać następną.
Jak tego uniknąć?

var StartTimeSpan = TimeSpan.Zero;
				var TimePeriod = TimeSpan.FromSeconds(1);
				while (Status)
				{
						if (client.Connected)
					{
						var timer = new System.Threading.Timer((e) =>
						{
							ServerMessage = sr.ReadLine();
							if (ServerMessage != null)
							{
								Console.WriteLine($"Użytkownik: {ServerMessage}\n");
								return;
							}
						}, null, StartTimeSpan, TimePeriod);
						Console.WriteLine("Wpisz wiadomość");
						ClientMessage = Console.ReadLine();
						sw.WriteLine(ClientMessage);
						sw.Flush();

Wedłóg mojej wizji to co jest w lambdzie powinno wykonywać się raz na sekundę, niezależnie od wszystkiego.
Prosiłbym jedynie o naprowadzenie mnie, a nie o gotowy kod :).

0

Cześć,

Nie do końca wiem czy rozumiem co chcesz zrobić. Czat zwykle tak działa że piszesz piszesz i enter. Chcesz żeby to co piszesz od razu się pokazywało?

W każdym razie, w Timerze jest ReadLine które blokuje wątek i czeka na Enter. Możesz użyć Console.Read albo czytać stream Console.OpenStandardInput do bufora.

0

Nie, teraz dzieje sie tak, że gdy wiadomość nadejdzie ja muszę wcisnąć Enter, aby program czekał na następną.

0

zrób odbieranie i wysyłanie w dwóch osobnych wątkach. Twój kod z timerem też powinien działać, choć lepsza jest tutaj nieskończona pętla z blokującą operacją I/O.
Daj więcej kodu, albo cały projekt - to co podałeś działa dobrze z zamockowanym serwerem.
Jedyny błąd że tworzysz nowy timer w pętli, za każdym enterem masz coraz więcej timerów czekających na wiadomość

0

Do sprawdzenia, czy znak został naciśnięty, użyj Console.KeyAvailable, a do pobrania znaku Console.ReadKey(true). Wynikiem tej drugiej funkcji jest obiekt, który we właściwości Key przechowuje wartość typu wyliczeniowego, a w KeyChar wartość typu char. Do ustawienia pozycji kursora użyj Console.SetCursorPosition. Jeżeli chcesz kontrolować pozycję kursora, to używaj Console.Write zamiast Console.WriteLine. Przejrzyj listę metod z klasy Console i zastanów się, do czego mogą Ci się przydać. Po opisie rozpoznasz, czy są dla Ciebie przydatne. Możesz pominąć te, których działania nie rozumiesz, bo pewnie nie będziesz ich potrzebował.

Napisałem przykładowy bardzo prymitywny kod pokazujący jak użyć tych funkcji. Nie użyłem Twojej obsługi przychodzących wiadomości i wielowątkowości, ale pokazałem tylko, jak można skorzystać z tego, co opisałem wyżej. Możesz rozwinąć swój program o obsługę pozostałych znaków sterujących, takich jak enter, delete, strzałki. Przychodzące wiadomości możesz trzymać w kolekcji i wyświetlać ich tylko tyle, ile się zmieści na obszarze dla nich przeznaczonym lub je przewijać.

Jeżeli chcesz to zrobić samodzielnie, to sprawdź mój przykład dopiero wtedy, gdy nie będziesz miał pomysłów jak to zrobić.

var message = "";
var incomingMessagesCount = 0;
const int windowWidth = 80;
const int windowHeight = 25;

Console.SetWindowSize(windowWidth, windowHeight);
Console.SetCursorPosition(0, windowHeight);

while (true)
{
    if (Console.KeyAvailable)
    {
        var consoleKey = Console.ReadKey(true);

        if (consoleKey.Key == ConsoleKey.Backspace)
        {
            message = message.Substring(0, Math.Max(0, message.Length - 1));
        }
        else
        {
            message += consoleKey.KeyChar;
        }

        Console.SetCursorPosition(0, windowHeight - 1);
        Console.Write(message.PadRight(windowWidth));
        Console.SetCursorPosition(message.Length, windowHeight - 1);
    }

    if (new Random().Next(100) == 0)
    {
        var incomingMessage = "Hello World!";
        Console.SetCursorPosition(0, incomingMessagesCount++);
        Console.Write(incomingMessage);
        Console.SetCursorPosition(message.Length, windowHeight - 1);
    }

    Thread.Sleep(50);                
}
0

Mój kod poniżej:
@Burmistrz, twój przykłąd sprawdzę w momencie, kiedy nie uda mi isę napisać tego samemu:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.IO;
namespace ChatClient
{
public class Program
	{
		static void Main(string[] args)
		{
			try
			{
				bool Status = true;
				string ServerMessage;
				string ClientMessage;
				TcpListener l = new TcpListener(9678);
				File.AppendAllText("log.txt", "Rozpoczynam pracę...\nRozpoczynam nasłuchiwanie na porcie 9768\n");
				l.Start();
				Console.WriteLine("OK");
				Socket client = l.AcceptSocket();
				Console.WriteLine("OK, nawiązano połączenie");
				File.AppendAllText("log.txt", "Nawiązano połączenie z klientem\n");
				NetworkStream ns = new NetworkStream(client);
				File.AppendAllText("log.txt", "Tworzę strumień zapisu wiadomości...\n");
				StreamWriter sw = new StreamWriter(ns);
				File.AppendAllText("log.txt", "Utworzono pomyślnie.\n");
				StreamReader sr = new StreamReader(ns);
				File.AppendAllText("log.txt", "Utworzono strumień odczytu wiadomości.\n");
				var StartTimeSpan = TimeSpan.Zero;
				var TimePeriod = TimeSpan.FromSeconds(1);
				while (Status)
				{
						if (client.Connected)
					{
						var timer = new System.Threading.Timer((e) =>
						{
							ServerMessage = sr.ReadLine();
							if (ServerMessage != null)
							{
								Console.WriteLine($"Użytkownik: {ServerMessage}\n");
								return;
							}
							else
							{
								return;
							}
						}, null, StartTimeSpan, TimePeriod);
						Console.WriteLine("Wpisz wiadomość");
						ClientMessage = Console.ReadLine();
						sw.WriteLine(ClientMessage);
						sw.Flush();
						File.AppendAllText("log.txt", $"Ty: {ClientMessage}\n");
					}
				}

				sr.Close();
				ns.Close();
				sw.Close();
				client.Close();


			}
			catch (Exception e)
			{
				Console.WriteLine($"Coś poszło nie tak: {e.Message}");

				throw;
			}
		}
	}
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1