简体   繁体   English

TCP/Server 我可以从另一个类调用Form1的组件

[英]TCP / Server I can from another class call the components of Form1

I have this example as a server.我有这个例子作为服务器。 The question that only works well for me on console.在控制台上只对我有效的问题。 I want to pass it to windows Form.我想将它传递给 Windows 窗体。 And I don't know how to apply it.而且我不知道如何应用它。

Because I understand that it is bad practice from another class such as creating a Form1 Method and using a Form1 object in the Server class.因为我知道这是另一个类的不好做法,例如创建 Form1 方法并在 Server 类中使用 Form1 对象。

As if in the server class I call the textbox or things like that.好像在服务器类中我调用文本框或类似的东西。

The question that I think I would have to adapt all the code back for windows Form?我认为我必须将所有代码改回 Windows 窗体的问题?

Or stop using the classes and use the typical TcpClient, TpcListener as in the videos that declare it at the moment in Form1.或者停止使用这些类并使用典型的 TcpClient、TpcListener,就像目前在 Form1 中声明它的视频一样。

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace Chatroom
{

    delegate void MessageEventHandler(object sender, MessageEventArgs e);

    class MessageEventArgs : EventArgs
    {
        public string Message { get; private set; }

        public MessageEventArgs(string message)
        {
            this.Message = message;
        }
    }

    class Server
    {
        private TcpListener serverSocket;
        private List<Worker> workers = new List<Worker>();

        public Server(int port)
        {
            //serverSocket = new TcpListener(port);// deprecated
            // the same way
            serverSocket = new TcpListener(IPAddress.Any, port);
            serverSocket.Start();
        }

        private void WaitForConnection()
        {
            while (true)
            {
                TcpClient socket = serverSocket.AcceptTcpClient();
                Worker worker = new Worker(socket);
                AddWorker(worker);
                worker.Start();
            }
        }

        private void Worker_MessageReceived(object sender, MessageEventArgs e)
        {
            BroadcastMessage(sender as Worker, e.Message);
        }

        private void Worker_Disconnected(object sender, EventArgs e)
        {
            RemoveWorker(sender as Worker);
        }

        private void AddWorker(Worker worker)
        {
            lock (this)
            {
                workers.Add(worker);
                worker.Disconnected += Worker_Disconnected;
                worker.MessageReceived += Worker_MessageReceived;
            }
        }

        private void RemoveWorker(Worker worker)
        {
            lock (this)
            {
                worker.Disconnected -= Worker_Disconnected;
                worker.MessageReceived -= Worker_MessageReceived;
                workers.Remove(worker);
                worker.Close();
            }
        }

        private void BroadcastMessage(Worker from, String message)
        {
            lock (this)
            {
                message = string.Format("{0}: {1}", from.Username, message);
                for (int i = 0; i < workers.Count; i++)
                {
                    Worker worker = workers[i];
                    if (!worker.Equals(from))
                    {
                        try
                        {
                            worker.Send(message);
                        }
                        catch (Exception)
                        {
                            workers.RemoveAt(i--);
                            worker.Close();
                        }
                    }
                }
            }
        }

        class Worker
        {
            public event MessageEventHandler MessageReceived;
            public event EventHandler Disconnected;
            private readonly TcpClient socket;
            private readonly Stream stream;
            public string Username { get; private set; } = null;

            public Worker(TcpClient socket)
            {
                this.socket = socket;
                this.stream = socket.GetStream();
            }

            public void Send(string message)
            {
                byte[] buffer = Encoding.UTF8.GetBytes(message);
                stream.Write(buffer, 0, buffer.Length);
            }

            public void Start()
            {
                new Thread(Run).Start();
            }

            private void Run()
            {
                byte[] buffer = new byte[2018];
                try
                {
                    while (true)
                    {
                        int receivedBytes = stream.Read(buffer, 0, buffer.Length);
                        if (receivedBytes < 1)
                            break;
                        string message = Encoding.UTF8.GetString(buffer, 0, receivedBytes);
                        if (Username == null)
                            Username = message;
                        else
                            MessageReceived?.Invoke(this, new MessageEventArgs(message));
                    }
                }
                catch (IOException) { }
                catch (ObjectDisposedException) { }
                Disconnected?.Invoke(this, EventArgs.Empty);
            }

            public void Close()
            {
                socket.Close();
            }
        }

        static void Main(string[] args)
        {
            try
            {
                Server server = new Server(3393);
                server.WaitForConnection();
            }
            catch (IOException) { }
        }
    }
}

The problem is this.问题是这个。 If I have Form1.如果我有 Form1.

As I relate it, as I do eg.正如我所涉及的那样,就像我所做的那样。 Every time a new Client is created it is added by a list box from the Server class.每次创建一个新的客户端时,它都会通过来自 Server 类的列表框添加。 In theory you can't or if you can or is it bad practice?理论上你不能,或者如果你可以,或者这是不好的做法?

Class Server{
private void RemoveWorker(Worker worker)
        {
            lock (this)
            {
                **textbox.text +="Cliente desconectado";**
                worker.Disconnected -= Worker_Disconnected;
                worker.MessageReceived -= Worker_MessageReceived;
                workers.Remove(worker);
                worker.Close();
            }
        }
}

How could it be done without being in the main WindForm class如果不在主要的 WindForm 类中怎么做

Here are steps to help you start.以下是帮助您开始的步骤。

  1. Create a new WinForms project in VisualStudio.在 VisualStudio 中创建一个新的WinForms项目。
  2. You project should build and show the form right away without you having to do anything.您的项目应该立即构建并显示表单,而无需执行任何操作。
  3. You should have Program.cs that contains the Main() method.您应该拥有包含Main()方法的Program.cs You do not need to change it.您不需要更改它。 This is what causes the Form1 to load and display.这就是导致Form1加载和显示的原因。
[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
}
  1. You can right-click on the Form1.cs and select View Code to see the code behind page.您可以右键单击Form1.cs并选择View Code以查看代码隐藏页面。
  2. There you will have the constructor that has InityializeConponent() method that creates all of your GUI "stuff".在那里,您将拥有具有InityializeConponent()方法的构造函数,该方法可创建您的所有 GUI“东西”。
  3. Add a listener to run when the Form loads.添加一个侦听器以在表单加载时运行。 This is where you can add your server stuff.这是您可以添加服务器内容的地方。
  4. Open your GUI designer, go to Form1 -> Properties and add a new function to the Load打开您的 GUI 设计器,转到Form1 -> Properties并将一个新函数添加到Load 加载事件
  5. This is where you will write your code.这是您编写代码的地方。 For example, you can create and start the server.例如,您可以创建并启动服务器。
private void Form1_Load(object sender, EventArgs e)
{
    try
    {
        Server server = new Server(3393);
        server.WaitForConnection();
    }
    catch (IOException) { // Put something here like a log }
}
  1. Your server can go to a new Class that can be in a new file like Server.cs .您的服务器可以转到一个新类,该类可以位于新文件中,例如Server.cs Just make sure that WaitForConnection() is public .只需确保WaitForConnection()public

This should get you started.这应该让你开始。 When you run into an issue, just create a new question on SO and make sure to add your latest code.当您遇到问题时,只需在 SO 上创建一个新问题并确保添加您的最新代码。

Some suggestions:一些建议:

  • Use a delegate to communicate between Server and the GUI使用delegate在服务器和 GUI 之间进行通信
  • You may want to run the Server in another thread.您可能希望在另一个线程中运行服务器。 Test it first to get it working and see if this is what you need/want首先测试它以使其正常工作,看看这是否是您需要/想要的
  • You don't normally want to run a server as WinForms project.您通常不希望将服务器作为 WinForms 项目运行。 If you accidently close the form, you kill your server.如果您不小心关闭了表单,就会杀死您的服务器。
  • Make sure to have a Form1_Close event and shut down your server there correctly确保有一个Form1_Close事件并在那里正确关闭您的服务器

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

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