C#TCP服务器到多个客户端(未知数量的客户端正在侦听)
我正在尝试编写一个小程序,它是从服务器和一些客户端构建的。 服务器将向客户端传输/推送文本消息(不允许客户端发送回服务器,所有客户端都应从服务器获取相同的文本消息) 我在这里和网上看到了一些关于这个问题的问题,但没有得到我想要的确切答案。 大多数解决方案是为每个客户端创建一个线程。但假设我并不总是知道在某个特定时间会有多少客户在收听。可能是2岁,也可能是30岁。 我知道有一种方法可以创建线程池,并让.NET处理线程分配问题,但从未有过良好的实践,我的线程知识也不太好。 现在,我有一个简单的服务器到客户端程序,它可以像预期的那样工作,但同样,只能使用一个客户端。 这是我的代码: 服务器:C#TCP服务器到多个客户端(未知数量的客户端正在侦听),c#,multithreading,tcp,client,server,C#,Multithreading,Tcp,Client,Server,我正在尝试编写一个小程序,它是从服务器和一些客户端构建的。 服务器将向客户端传输/推送文本消息(不允许客户端发送回服务器,所有客户端都应从服务器获取相同的文本消息) 我在这里和网上看到了一些关于这个问题的问题,但没有得到我想要的确切答案。 大多数解决方案是为每个客户端创建一个线程。但假设我并不总是知道在某个特定时间会有多少客户在收听。可能是2岁,也可能是30岁。 我知道有一种方法可以创建线程池,并让.NET处理线程分配问题,但从未有过良好的实践,我的线程知识也不太好。 现在,我有一个简单的服务器
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows;
namespace NetMessageServerWpf
{
public partial class MainWindow : Window
{
TcpClient client;
public MainWindow()
{
InitializeComponent();
this.tcpListener = new TcpListener(IPAddress.Any, 3000);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
private void btnSend_Click(object sender, RoutedEventArgs e)
{
if(client == null || !client.Connected)
client = this.tcpListener.AcceptTcpClient();
msg = txtMessage.Text;
SendTCP(client);
}
public TcpListener tcpListener;
public Thread listenThread;
private string msg;
private void ListenForClients()
{
this.tcpListener.Start();
}
public void SendTCP(TcpClient tcpClient)
{
NetworkStream clientStream = tcpClient.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(this.msg);
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
}
}
客户:
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace NetClientSideWpf
{
class Client : Base
{
private string messageString;
public string MessageString
{
get { return messageString; }
set
{
messageString = value;
OnPropertyChanged("MessageString");
}
}
public Client()
{
ConnectToServer();
}
public void ConnectToServer()
{
TcpClient client = new TcpClient();
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3000);
client.Connect(serverEndPoint);
NetworkStream clientStream = client.GetStream();
Thread ServerThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
ServerThread.Start(client);
}
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] message = new byte[4096];
int bytesRead;
while (true)
{
bytesRead = 0;
try
{
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
break;
}
if (bytesRead == 0)
{
break;
}
ASCIIEncoding encoder = new ASCIIEncoding();
MessageString = encoder.GetString(message, 0, bytesRead);
}
}
}
}
任何帮助都可以!:) 我认为首先应该在应用程序开始时启动侦听器。 然后查看输入连接的间隔(计时器)(TCPListener.Pending) 如果获得连接,则应将TCPClient保存在列表中。 在按钮上,单击将消息发送给您的客户 我认为这不是最好的解决方案,但它是一个没有多线程的解决方案;-) 我写了一些示例代码,希望对您有所帮助(未经测试):
公共部分类主窗口:窗口
{
专用TcpListener\u服务器;
私人列表(u connectedClients);;
公共主窗口()
{
初始化组件();
_服务器=新的TcpListener(IPAddress.Any,3000);
_connectedClients=新列表();
_server.Start();
调度程序计时器=新调度程序();
timer.Interval=TimeSpan.FromSeconds(1);//每1秒一次!
timer.Tick+=定时器_Tick;
timer.Start();
}
私有void发送消息(字符串消息)
{
ascienceoding编码器=新的ascienceoding();
字节[]缓冲区=编码器.GetBytes(消息);
foreach(连接客户端中的var客户端)
{
NetworkStream clientStream=client.GetStream();
Write(buffer,0,buffer.Length);
clientStream.Flush();
}
}
无效计时器勾号(对象发送方,事件参数e)
{
Debug.WriteLine(“勾选”);
Title=“你好”;
如果(_server.Pending())
{
_connectedClients.Add(_server.AcceptTcpClient());
}
}
}
我已经编辑了我的问题,我忘了提到所有客户都应该收到相同的短信(因此我认为没有必要“列出”他们)。我不介意使用线程,但我如何才能确保我有足够的线程等等。你必须列出它们。每个连接的客户端都有一个TCP客户端。所以你必须记住列表中的所有内容。我不知道TCPListener上有什么属性或方法可以向所有客户端发送消息。好的,我将尝试编写一个示例!似乎工作很好,所以谢谢:)有一件事困扰着我。。。每1秒检查一次连接,这不是在消耗资源吗?这就是你说这不是最好的解决方案的原因吗?对!我会使用一个带有while循环的线程,并在那里检查传入的连接。但是你必须锁定你的客户名单。
public partial class MainWindow : Window
{
private TcpListener _server;
private List<TcpClient> _connectedClients;
public MainWindow()
{
InitializeComponent();
_server = new TcpListener(IPAddress.Any, 3000);
_connectedClients = new List<TcpClient>();
_server.Start();
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(1); //every 1 sec!
timer.Tick += timer_Tick;
timer.Start();
}
private void SendMessage(string message)
{
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(message);
foreach (var client in _connectedClients)
{
NetworkStream clientStream = client.GetStream();
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
}
void timer_Tick(object sender, EventArgs e)
{
Debug.WriteLine("Tick");
Title = "hello";
if (_server.Pending())
{
_connectedClients.Add(_server.AcceptTcpClient());
}
}
}