C# 理解委托流程

C# 理解委托流程,c#,.net,sockets,delegates,tcplistener,C#,.net,Sockets,Delegates,Tcplistener,首先,我想道歉,如果这似乎是我不应该张贴这个问题。在过去的两周里,我一直在努力理解这段代码,但都无济于事 我的主要问题是理解这个代表在这里是如何工作的 messageInformer = new MessageInformer(this.Broadcast); 我无法使用调试器跟踪代码,因为VS不允许我这样做。我了解套接字连接、发送和接收,但我不知道代理在这里是如何工作的。我注意到,在将多个客户端连接到服务器之后,当一个客户端向服务器发送消息时,其他客户端会收到与服务器相同的消息 我理解委托是

首先,我想道歉,如果这似乎是我不应该张贴这个问题。在过去的两周里,我一直在努力理解这段代码,但都无济于事

我的主要问题是理解这个代表在这里是如何工作的

messageInformer = new MessageInformer(this.Broadcast);
我无法使用调试器跟踪代码,因为VS不允许我这样做。我了解套接字连接、发送和接收,但我不知道代理在这里是如何工作的。我注意到,在将多个客户端连接到服务器之后,当一个客户端向服务器发送消息时,其他客户端会收到与服务器相同的消息

我理解委托是一个函数指针,我知道委托的基础知识

请有人向我解释一下如何使用该代表的流程

查找以下所有代码:

Server.cs

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

namespace SimpleChatServer.Communication
{
    class Server
    {
        private Socket serverSock;
        private List<ClientHandler> clientsConnected = new List<ClientHandler>();
        private MessageInformer messageInformer;
        public Server()
        {
            serverSock = new Socket(
                AddressFamily.InterNetwork,
                SocketType.Stream,
                ProtocolType.Tcp);
            Console.WriteLine("Socket created");
            serverSock.Bind(
              new IPEndPoint(IPAddress.Loopback, 8055));
            Console.WriteLine("Binding done");
            serverSock.Listen(5);
            Console.WriteLine("Listening started");
            messageInformer = new MessageInformer(this.Broadcast);
        }

        public void StartAccepting()
        {

            while (true)
            {
                clientsConnected.Add(new ClientHandler(serverSock.Accept(), messageInformer));
                Thread thread = new Thread(new ParameterizedThreadStart(clientsConnected.Last().StartReceiving));
                thread.Start();
                Console.WriteLine("New Client accepted");
            }
        }


        private void Broadcast(Socket caller, string message)
        {
            foreach (var item in clientsConnected)
            {
                if(!item.ClientSock.Equals(caller))
                item.ClientSock.Send(Encoding.UTF8.GetBytes(message));
            }
        }

    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;

namespace SimpleChatServer.Communication
{
    class ClientHandler
    {
        private Socket clientSock;
        private MessageInformer informer;

        public Socket ClientSock
        {
            get { return clientSock; }
            //set { clientSock = value; }
        }

        private byte[] buffer = new byte[512];

        public ClientHandler(Socket clientSock, MessageInformer informer)
        {
            this.clientSock = clientSock;
            this.informer = informer;


        }

        /// <summary>
        ///  Receive messages from the client
        /// </summary>
        /// <param name="obj"></param>
        public void StartReceiving(object obj)
        {
            int length;
            string name = "";
            string message = "";

            #region  Handle Name
            do
            {
                length = clientSock.Receive(buffer);
                name += Encoding.UTF8.GetString(buffer, 0, length);

            } while (!name.Contains("\r\n"));

            name = name.Substring(0, name.Length - 2);

            clientSock.Send(Encoding.UTF8.GetBytes("hello " + name + "\r\n"));

            #endregion 

            while (true)
            {
                length = clientSock.Receive(buffer);
                message += Encoding.UTF8.GetString(buffer, 0, length);
                if (message.Contains("\r\n"))
                {

                    Console.Write(name + ": " + message);
                    informer(clientSock, name + ": " + message);
                    message = "";

                }
            }

        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;

namespace SimpleChatServer.Communication
{
  public delegate void  MessageInformer(Socket caller, string message);
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SimpleChatServer.Communication;

namespace SimpleChatServer
{
    class Program
    {
        static void Main(string[] args)
        {

            Server server = new Server();
            server.StartAccepting();
            server.StartAccepting();
            Console.ReadLine();
        }
    }
}
program.cs

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

namespace SimpleChatServer.Communication
{
    class Server
    {
        private Socket serverSock;
        private List<ClientHandler> clientsConnected = new List<ClientHandler>();
        private MessageInformer messageInformer;
        public Server()
        {
            serverSock = new Socket(
                AddressFamily.InterNetwork,
                SocketType.Stream,
                ProtocolType.Tcp);
            Console.WriteLine("Socket created");
            serverSock.Bind(
              new IPEndPoint(IPAddress.Loopback, 8055));
            Console.WriteLine("Binding done");
            serverSock.Listen(5);
            Console.WriteLine("Listening started");
            messageInformer = new MessageInformer(this.Broadcast);
        }

        public void StartAccepting()
        {

            while (true)
            {
                clientsConnected.Add(new ClientHandler(serverSock.Accept(), messageInformer));
                Thread thread = new Thread(new ParameterizedThreadStart(clientsConnected.Last().StartReceiving));
                thread.Start();
                Console.WriteLine("New Client accepted");
            }
        }


        private void Broadcast(Socket caller, string message)
        {
            foreach (var item in clientsConnected)
            {
                if(!item.ClientSock.Equals(caller))
                item.ClientSock.Send(Encoding.UTF8.GetBytes(message));
            }
        }

    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;

namespace SimpleChatServer.Communication
{
    class ClientHandler
    {
        private Socket clientSock;
        private MessageInformer informer;

        public Socket ClientSock
        {
            get { return clientSock; }
            //set { clientSock = value; }
        }

        private byte[] buffer = new byte[512];

        public ClientHandler(Socket clientSock, MessageInformer informer)
        {
            this.clientSock = clientSock;
            this.informer = informer;


        }

        /// <summary>
        ///  Receive messages from the client
        /// </summary>
        /// <param name="obj"></param>
        public void StartReceiving(object obj)
        {
            int length;
            string name = "";
            string message = "";

            #region  Handle Name
            do
            {
                length = clientSock.Receive(buffer);
                name += Encoding.UTF8.GetString(buffer, 0, length);

            } while (!name.Contains("\r\n"));

            name = name.Substring(0, name.Length - 2);

            clientSock.Send(Encoding.UTF8.GetBytes("hello " + name + "\r\n"));

            #endregion 

            while (true)
            {
                length = clientSock.Receive(buffer);
                message += Encoding.UTF8.GetString(buffer, 0, length);
                if (message.Contains("\r\n"))
                {

                    Console.Write(name + ": " + message);
                    informer(clientSock, name + ": " + message);
                    message = "";

                }
            }

        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;

namespace SimpleChatServer.Communication
{
  public delegate void  MessageInformer(Socket caller, string message);
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SimpleChatServer.Communication;

namespace SimpleChatServer
{
    class Program
    {
        static void Main(string[] args)
        {

            Server server = new Server();
            server.StartAccepting();
            server.StartAccepting();
            Console.ReadLine();
        }
    }
}

让我们从上到下开始:

public delegate void  MessageInformer(Socket caller, string message);
这是委托定义,这里还没有完成任何工作

messageInformer = new MessageInformer(this.Broadcast);
这将私有变量messageInformer(属于messageInformer委托类型)设置为一个新值:一个以此类的方法广播为目标的实例化委托。它必须具有与委托类型相同的参数,才能作为此委托的目标应用。比较这些参数:

public delegate **void**  MessageInformer(**Socket** caller, **string** message);
private **void** Broadcast(**Socket** caller, **string** message)
调用
messageInformer(mySocket,myMessage)
现在将调用重定向到
Server.Broadcast(mySocket,MyMessage)
,无论从何处调用此委托,因为此委托绑定到服务器广播方法的此实例,并且不依赖于调用它的上下文

clientsConnected.Add(new ClientHandler(serverSock.Accept(), messageInformer));
这一行使用一个新连接的套接字创建一个新的ClientHandler,并为它提供messageInformerDelegate,它仍然指向Server.Broadcast,即使它现在被提供给ClientHandler。然后在ClientHandler中将代理另存为
通知者

informer(clientSock, name + ": " + message);
ClientHandler.StartReceiving方法中的这一行现在调用Server.BroadCast方法,提供它自己的套接字和它收到的消息。它可以被转换成
myServer.Broadcast(clientSock,name+”:“+message)如果您在ClientHandler中拥有对服务器的引用

informer(clientSock, name + ": " + message);

然后,Server.Broadcast方法循环遍历所有套接字,转发接收到的消息,检查委托调用提供的套接字(在本例中始终是调用Clienthandler的套接字)是否正确将是此消息转发到的套接字。

首先,您应该了解如何在这样的场景中使用调试器。(启动多个工作室,每个客户端一个,将一个连接到服务器)。此外,您可以使用跟踪消息和/或Console.Write*()消息来遵循此代码的流程。是的,套接字代码是复杂的。。。