Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#TCP服务器到多个客户端(未知数量的客户端正在侦听)_C#_Multithreading_Tcp_Client_Server - Fatal编程技术网

C#TCP服务器到多个客户端(未知数量的客户端正在侦听)

C#TCP服务器到多个客户端(未知数量的客户端正在侦听),c#,multithreading,tcp,client,server,C#,Multithreading,Tcp,Client,Server,我正在尝试编写一个小程序,它是从服务器和一些客户端构建的。 服务器将向客户端传输/推送文本消息(不允许客户端发送回服务器,所有客户端都应从服务器获取相同的文本消息) 我在这里和网上看到了一些关于这个问题的问题,但没有得到我想要的确切答案。 大多数解决方案是为每个客户端创建一个线程。但假设我并不总是知道在某个特定时间会有多少客户在收听。可能是2岁,也可能是30岁。 我知道有一种方法可以创建线程池,并让.NET处理线程分配问题,但从未有过良好的实践,我的线程知识也不太好。 现在,我有一个简单的服务器

我正在尝试编写一个小程序,它是从服务器和一些客户端构建的。 服务器将向客户端传输/推送文本消息(不允许客户端发送回服务器,所有客户端都应从服务器获取相同的文本消息) 我在这里和网上看到了一些关于这个问题的问题,但没有得到我想要的确切答案。 大多数解决方案是为每个客户端创建一个线程。但假设我并不总是知道在某个特定时间会有多少客户在收听。可能是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());
        }
    }

}