简体   繁体   English

C#TCP:接收从TCPClient发送到TCPListener的数据

[英]C# TCP: Receive data sent to TCPListener from TCPClient

Yesterday I started a project where you can chat with people in a specific chat room in a C# Console Application. 昨天我启动了一个项目,您可以在C#控制台应用程序的特定聊天室中与人聊天。 There is a TCPListener on the server-side that continuously listens for incoming connections and handles each incoming connection on a separate thread. 服务器端有一个TCPListener,它不断侦听传入的连接并在单独的线程上处理每个传入的连接。 On the client-side you can connect to this listener by entering an IP address and nickname and you are connected to the TCPListener. 在客户端,您可以通过输入IP地址和昵称来连接到此侦听器,并且已连接到TCPListener。

I am able to send messages from Client => Server and the messages arrive at the server, but when multiple clients are connected the other clients won't see my message. 我能够从客户端=>服务器发送消息,并且消息到达服务器,但是当多个客户端连接时,其他客户端将看不到我的消息。

For instance, I have two clients connected to the listener: one with nickname 'user1' and one with nickname 'user2'. 例如,我有两个客户端连接到侦听器:一个客户端的昵称为“ user1”,另一个客户端的昵称为“ user2”。 When user1 sends a message, the server receives it. 当user1发送消息时,服务器会接收到该消息。 When user2 sends a message, the server receives it too. 当user2发送消息时,服务器也接收到该消息。 But user1 does not see what user2 sent to the server and vice-versa. 但是user1看不到user2发送到服务器的内容,反之亦然。

My question 我的问题

My question is: 我的问题是:

How can I make TCPClients connected to the TCPListener receive the messages from other TCPClients? 如何使连接到TCPListener的TCPClient接收来自其他TCPClient的消息?

Additional information 附加信息

I've added some comments to make it easy to understand the methods I used. 我添加了一些注释,以使其易于理解我使用的方法。 The listener listens on port 8345. 侦听器侦听端口8345。

Client 客户

    public static void Connect(string serverIP, string nickname)
    {
        try
        {
            TcpClient client = new TcpClient();
            NetworkStream stream = null;
            MessageHelper helper = null;

            client.Connect(serverIP, PORT);
            stream = client.GetStream();
            helper = new MessageHelper(client, stream);
            helper.SendMessage($"!nickname={nickname}");

            Log("Connected!");

            Thread receiveThread = new Thread(new ThreadStart(() =>
            {
                while (true)
                {
                    // Get messages from other senders
                    helper.ReadMessage();
                    Thread.Sleep(300);
                }
            }));

            receiveThread.Start();

            while (Util.IsClientConnected(client))
            {
                Console.Write(" > ");
                var message = Console.ReadLine();

                if (!string.IsNullOrWhiteSpace(message))
                {
                    try
                    {
                        helper.SendMessage(message);
                    }
                    catch (IOException)
                    {
                        Log("The server closed unexpectedly.");
                    }
                }                        
            }

            Log("Disconnected.");
        }
        catch (SocketException ex)
        {
            Log("SocketException: " + ex.ToString());
        }
    }

Server 服务器

    public static bool IsListening;
    private const int PORT = 8345;

    public static void HandleClient(object _client)
    {
        TcpClient client = (TcpClient)_client;
        NetworkStream stream = null;
        MessageHelper helper = null;
        var ipAddress = MessageHelper.GetIpInformation(client).IpAddress.ToString();
        stream = client.GetStream();
        helper = new MessageHelper(client, stream);

        // Initial read, assuming this will be a '!nickname' command it will set the nickname
        helper.ReadMessage();
        Log($"{helper.Nickname} ({ipAddress}) connected.");

        while (Util.IsClientConnected(client))
        {
            try
            {
                // Check every 300 ms for a new message and print it to the screen.
                helper.ReadMessage();
            }
            catch (IOException)
            {
                Log($"{helper.Nickname} disconnected.");
            }

            Thread.Sleep(300);
        }
    }

    public static void StartListener()
    {
        TcpListener listener = null;
        IPAddress ipAddress = IPAddress.Any;

        listener = new TcpListener(ipAddress, PORT);
        try
        {
            listener.Start();
            IsListening = true;
            Log($"Listener started at {ipAddress}:{PORT}.");
        }
        catch (Exception ex)
        {
            Log("Error: " + ex.ToString());
        }

        while (IsListening)
        {
            // Check if listener is handling a pending connection, if not, wait 250 ms.
            if (!listener.Pending())
            {
                Thread.Sleep(250);
                continue;
            }

            // Client connected, handle at a separate thread.
            TcpClient client = listener.AcceptTcpClient();
            Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClient));
            clientThread.Start(client);
        }
    }

MessageHelper.cs MessageHelper.cs

public class MessageHelper
{
    public string Nickname { get; set; }
    public TcpClient Client { get; set; }
    public NetworkStream Stream { get; set; }

    public MessageHelper(TcpClient client, NetworkStream stream)
    {
        Client = client;
        Stream = stream;
    }

    public static IpInformation GetIpInformation(TcpClient client, bool isRemote = true)
    {
        string fullHostname;

        if (isRemote)
            fullHostname = client.Client.RemoteEndPoint.ToString();
        else
            fullHostname = client.Client.LocalEndPoint.ToString();

        IpInformation info = new IpInformation()
        {
            IpAddress = IPAddress.Parse(fullHostname.Split(':')[0]),
            Port = int.Parse(fullHostname.Split(':')[1])
        };

        return info;
    }

    public string GetMessageFormat(string message)
    {
        DateTime dateTime = DateTime.Now;
        return $" [{dateTime.ToShortTimeString()}] <{Nickname}>: {message}";
    }

    public void ReadMessage()
    {
        byte[] data = new byte[256];
        int byteCount = Stream.Read(data, 0, data.Length);
        string ipAddress = GetIpInformation(Client).IpAddress.ToString();
        string message = Encoding.ASCII.GetString(data, 0, byteCount);

        // Check if message is a command
        if (message.StartsWith("!"))
        {
            try
            {
                // Command format is >> !command=value <<
                string[] commandSplit = message.TrimStart('!').Split('=');
                string command = commandSplit[0];
                string value = commandSplit[1];

                if (command == "nickname")
                {
                    Nickname = value;
                }
                else
                {
                    Log("This command is not found.");
                }
            }
            catch (Exception)
            {
            }
        }
        else
        {
            // Regular message, print it to the console window.
            Console.ForegroundColor = ConsoleColor.DarkYellow;
            Console.WriteLine(GetMessageFormat(message));
            Console.ResetColor();
        }
    }

    public void SendMessage(string message)
    {
        byte[] data = Encoding.ASCII.GetBytes(message);
        Stream.Write(data, 0, data.Length);

        if (!message.StartsWith("!"))
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine(GetMessageFormat(message));
            Console.ResetColor();
        }
        else
        {
            // Issue the '!nickname' command
            if (message.StartsWith("!nickname"))
            {
                try
                {
                    Nickname = message.TrimStart('!').Split('=')[1];
                }
                catch (IndexOutOfRangeException)
                {
                    Log("Please enter an argument for this command.");
                }
            }
        }
    }
}

In the MessageHelper.cs class ReadMessage method you are not storing the messages or you are not broadcasting the messages to all the clients. MessageHelper.cs类的ReadMessage方法中,您没有存储消息,或者没有将消息广播给所有客户端。

To broadcast 播放

  1. Create an Event in MessageHelper and raise the event at Console.WriteLine(GetMessageFormat(message)); 在MessageHelper中创建一个事件,并在Console.WriteLine(GetMessageFormat(message));处引发该事件Console.WriteLine(GetMessageFormat(message)); .
  2. Pass the message in EventHandler in the Event. 在事件的EventHandler中传递消息。
  3. In Client.cs file, Handle the event to recieve all the messages 在Client.cs文件中,处理事件以接收所有消息

Sample Code 样例代码

In MessageHelper Class declare event as MessageHelper类中,将event声明为

public event EventHandler ReadMessageEvent;

In ReadMessage Method at Console.WriteLine(GetMessageFormat(message)); Console.WriteLine(GetMessageFormat(message)); ReadMessage方法中Console.WriteLine(GetMessageFormat(message)); replace with 用。。。来代替

if (ReadMessageEvent!= null)
        ReadMessageEvent.Invoke(GetMessageFormat(message), null);

In Client class try block add below code Client类的try块中,添加以下代码

helper.ReadMessageEvent += ReadMessageEvent_HandleEvent;

 private void ReadMessageEvent_HandleEvent(object sender, EventArgs e)
 {
   string message = sender as string;
   Console.WriteLine(message);           
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM