昨天我启动了一个项目,您可以在C#控制台应用程序的特定聊天室中与人聊天。服务器端有一个TCPListener,它不断侦听传入的连接并在单独的线程上处理每个传入的连接。在客户端,您可以通过输入IP地址和昵称来连接到此侦听器,并且您已连接到TCPListener。
我能够从 Client => Server 发送消息,并且消息到达服务器,但是当连接多个客户端时,其他客户端将看不到我的消息。
例如,我有两个客户端连接到侦听器:一个客户端的昵称为“ user1”,另一个客户端的昵称为“ user2”。当user1发送消息时,服务器会接收到该消息。当user2发送消息时,服务器也接收到该消息。但是user1看不到user2发送到服务器的内容,反之亦然。
我的问题
我的问题是:
如何使连接到TCPListener的TCPClient接收来自其他TCPClient的消息?
其他信息
我添加了一些注释以使您易于理解我使用的方法。侦听器侦听端口8345。
客户
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());
}
}
服务器
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
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.");
}
}
}
}
}
答案 0 :(得分:0)
在MessageHelper.cs
类ReadMessage
方法中,您没有存储消息,或者没有将消息广播给所有客户端。
要广播
Console.WriteLine(GetMessageFormat(message));
处引发该事件。 示例代码
在MessageHelper
类中,声明事件为
public event EventHandler ReadMessageEvent;
在ReadMessage
中的Console.WriteLine(GetMessageFormat(message));
方法中替换为
if (ReadMessageEvent!= null)
ReadMessageEvent.Invoke(GetMessageFormat(message), null);
在Client
类的try块中,添加以下代码
helper.ReadMessageEvent += ReadMessageEvent_HandleEvent;
private void ReadMessageEvent_HandleEvent(object sender, EventArgs e)
{
string message = sender as string;
Console.WriteLine(message);
}