Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.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#中的异步套接字服务器,通过套接字服务器进行客户端到客户端的通信_C#_Sockets_Asynchronous_Socketserver - Fatal编程技术网

C#中的异步套接字服务器,通过套接字服务器进行客户端到客户端的通信

C#中的异步套接字服务器,通过套接字服务器进行客户端到客户端的通信,c#,sockets,asynchronous,socketserver,C#,Sockets,Asynchronous,Socketserver,我正在尝试使用c#开发服务器/客户端异步套接字。我遵循了链接指南。在我的例子中,套接字服务器监听特定的端点,许多客户端可以一次连接到服务器,客户端可以和服务器对话,服务器可以和客户端对话。假设客户端1和客户端2与服务器连接,客户端1可以向服务器发送消息,服务器可以向客户端1发送消息,客户端2的情况也是如此。现在我希望客户端能够通过服务器相互通信。例如客户端2希望与客户端1通信,因为客户端2将向服务器发送消息(此消息将包含一些预设字符;),然后服务器将从客户端2接收文本,并获取客户端1的处理程序并

我正在尝试使用c#开发服务器/客户端异步套接字。我遵循了链接指南。在我的例子中,套接字服务器监听特定的端点,许多客户端可以一次连接到服务器,客户端可以和服务器对话,服务器可以和客户端对话。假设客户端1和客户端2与服务器连接,客户端1可以向服务器发送消息,服务器可以向客户端1发送消息,客户端2的情况也是如此。现在我希望客户端能够通过服务器相互通信。例如客户端2希望与客户端1通信,因为客户端2将向服务器发送消息(此消息将包含一些预设字符;),然后服务器将从客户端2接收文本,并获取客户端1的处理程序并将此消息发送给客户端1,客户端1将响应服务器,现在我想将客户机1对该消息的响应发送给客户机2,但我不知道如何做,因为客户机1通过其自己的处理程序与服务器进行通信,我很震惊,非常感谢您的帮助!! 我的代码如下:

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



namespace SocketServer
{
    // State object for reading client data asynchronously  
    public class StateObject
    {
        // Client  socket.  
        public Socket workSocket = null;
        // Size of receive buffer.  
        public const int BufferSize = 1024;
        // Receive buffer.  
        public byte[] buffer = new byte[BufferSize];
        // Received data string.  
        public StringBuilder sb = new StringBuilder();

        public int clientNumber;
    }
    public class AsyncSocketServer
    {
        public static ManualResetEvent allDone = new ManualResetEvent(false);

        public static Dictionary<int, StateObject> Clients = new Dictionary<int, StateObject>();

        public static int connectedClient = 0;




        public AsyncSocketServer()
        {


        } 
        public static void startListening() {

            Byte[] bytes = new Byte[1024];
            int Port = 1122;

            IPAddress IP = IPAddress.Parse("127.0.0.1");
            IPEndPoint EP = new IPEndPoint(IP, Port);
            Socket listner = new Socket(IP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);



            try
            {
                listner.Bind(EP);
                listner.Listen(100);

                while (true)
                {
                   allDone.Reset();

                    Console.WriteLine("Waiting for the Connection......");

                    listner.BeginAccept(new AsyncCallback(AcceptCallBack), listner);

                    allDone.WaitOne();
                }


            }
            catch(Exception e)
            {
                Console.WriteLine("Exception Occured ! in start listening method "+e.ToString());
            }

             Console.WriteLine("\nPress ENTER to continue...");  
            Console.Read();  

        }

        public static void AcceptCallBack(IAsyncResult ar)
        {
            connectedClient++;
            Console.WriteLine("client number " + connectedClient);
            allDone.Set();



            Socket listner = (Socket)  ar.AsyncState;
            Socket handler = listner.EndAccept(ar);

            StateObject state = new StateObject();
            state.clientNumber = connectedClient;

            Clients.Add(connectedClient, state);
           Console.WriteLine("total clients {0}",Clients.Count());

            state.workSocket = handler;
            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize,0,new AsyncCallback(ReadCallBack),state);

        }
        public static void ReadCallBack(IAsyncResult ar)
        {  

        String content = String.Empty;



        // Retrieve the state object and the handler socket  
        // from the asynchronous state object.  
        try { 
        StateObject state = (StateObject) ar.AsyncState;
        state.sb.Clear();
        Socket handler = state.workSocket;  

        // Read data from the client socket.   
        int bytesRead = handler.EndReceive(ar);  

        if (bytesRead > 0) {  
            // There  might be more data, so store the data received so far.  
            state.sb.Append(Encoding.ASCII.GetString(  
                state.buffer,0,bytesRead));  

            // Check for end-of-file tag. If it is not there, read   
            // more data.  

            content = state.sb.ToString();

            if (content.Substring(0, 3) == "cmd") {
                foreach (StateObject Client in Clients.Values) {
                    if (Client.clientNumber == 1) { 
                        Console.WriteLine("value is "+Client.clientNumber);
                        if (isClientConnected(Client.workSocket)){
                            Send(Client.workSocket, "did you receive my message");
                            //now client number 1 will response through its own handler, but i want to get response of 
                            //client number 1 and return this response to client number 2

                        }
                        else {
                            string responsemsg = "client number " + Client.clientNumber + " is disconnected !";
                            Console.WriteLine(responsemsg);
                            Send(handler,responsemsg);
                        }
                    }

                }
            }

            Console.WriteLine("Read {0} bytes from client {1} socket. \n Data : {2}",
                    content.Length, state.clientNumber,content);
            // Echo the data back to the client.  

            if (isClientConnected(handler))
            {
                Send(handler, content);
            }
            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallBack), state);

        }
        }
        catch (SocketException e)
        {
            //once if any client disconnected then control will come into this block
            Console.WriteLine("Socket Exception Occured in Read Call Back : " + e.Message.ToString());

        }
        catch (Exception e)
        {
            //once if any client disconnected then control will come into this block
            Console.WriteLine("Exception Occured in Read Call Back : " + e.Message.ToString());

        }
        }
        private static void Send(Socket handler, String data)
        {
            // Convert the string data to byte data using ASCII encoding.  
            byte[] byteData = Encoding.ASCII.GetBytes(data);

            // Begin sending the data to the remote device.  
            handler.BeginSend(byteData, 0, byteData.Length, 0,
                new AsyncCallback(SendCallback), handler);
        }

        private static void SendCallback(IAsyncResult ar)
        {
            try
            {
                // Retrieve the socket from the state object.  
                Socket handler = (Socket)ar.AsyncState;

                // Complete sending the data to the remote device.  
                int bytesSent = handler.EndSend(ar);
                Console.WriteLine("Sent {0} bytes to client.", bytesSent);



                //handler.Shutdown(SocketShutdown.Both);
                //handler.Close();

            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        public static bool isClientConnected(Socket handler){

            return handler.Connected;
        }
        public static int Main(string[] args)
        {

            startListening();


            return 0;


        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用系统线程;
使用System.Threading.Tasks;
Net系统;
使用System.Net.Sockets;
命名空间SocketServer
{
//用于异步读取客户端数据的状态对象
公共类状态对象
{
//客户端套接字。
公共套接字工作组=null;
//接收缓冲区的大小。
public const int BufferSize=1024;
//接收缓冲区。
公共字节[]缓冲区=新字节[BufferSize];
//接收到的数据字符串。
公共StringBuilder sb=新StringBuilder();
公共int客户号;
}
公共类AsyncSocketServer
{
public static ManualResetEvent allDone=新的ManualResetEvent(false);
公共静态字典客户端=新字典();
公共静态int connectedClient=0;
公共AsyncSocketServer()
{
} 
公共静态侦听(){
字节[]字节=新字节[1024];
int端口=1122;
IPAddress IP=IPAddress.Parse(“127.0.0.1”);
IPEndPoint EP=新IPEndPoint(IP,端口);
Socket listner=新套接字(IP.AddressFamily、SocketType.Stream、ProtocolType.Tcp);
尝试
{
listner.Bind(EP);
listner.听(100);
while(true)
{
全部完成。重置();
Console.WriteLine(“等待连接……”);
beginacept(新的异步回调(AcceptCallBack),listner);
全部完成。WaitOne();
}
}
捕获(例外e)
{
Console.WriteLine(“启动侦听方法中发生异常”+e.ToString());
}
Console.WriteLine(“\n按ENTER继续…”);
Console.Read();
}
公共静态无效接受回调(IAsyncResult ar)
{
connectedClient++;
Console.WriteLine(“客户端号码”+连接的客户端);
allDone.Set();
Socket listner=(Socket)ar.AsyncState;
套接字处理程序=listner.EndAccept(ar);
StateObject状态=新的StateObject();
state.clientNumber=connectedClient;
Clients.Add(connectedClient,state);
WriteLine(“总客户端{0}”,clients.Count());
state.workSocket=处理程序;
BeginReceive(state.buffer,0,StateObject.BufferSize,0,新异步回调(ReadCallBack),state);
}
公共静态void ReadCallBack(IAsyncResult ar)
{  
String content=String.Empty;
//检索状态对象和处理程序套接字
//从异步状态对象。
试试{
StateObject状态=(StateObject)ar.AsyncState;
把某人说清楚;
套接字处理程序=state.workSocket;
//从客户端套接字读取数据。
int bytesRead=handler.EndReceive(ar);
如果(字节读取>0){
//可能会有更多数据,因此请存储到目前为止收到的数据。
state.sb.Append(Encoding.ASCII.GetString(
state.buffer,0,bytesRead));
//检查文件结尾标记。如果不存在,请读取
//更多数据。
content=state.sb.ToString();
if(content.Substring(0,3)=“cmd”){
foreach(客户端中的StateObject客户端。值){
如果(Client.clientNumber==1){
Console.WriteLine(“值为”+Client.clientNumber);
如果(iClientConnected(Client.workSocket)){
发送(Client.workSocket,“您收到我的邮件了吗”);
//现在,客户端1将通过它自己的处理程序进行响应,但我想得到
//客户端1并将此响应返回给客户端2
}
否则{
字符串responsemsg=“client number”+client.clientNumber+“已断开连接!”;
控制台写入线(responsemsg);
发送(处理程序、响应msg);
}
}
}
}
WriteLine(“从客户端{1}套接字读取{0}字节。\n数据:{2}”,
content.Length,state.clientNumber,content);
//将数据回显到客户端。
if(iClient已连接(处理程序))
{
发送(处理程序、内容);
}
BeginReceive(state.buffer,0,StateObject.BufferSize,0,新异步回调(ReadCallBack),st
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using DotNetty.Transport.Channels;
using Newtonsoft.Json;
using System.IO;

namespace MultiClientSocketExample
{
    public enum Command
    {
        Register = 1,  // Register a new client
        SendToClient = 2, // Send a message from one client to antoher
        DoClientAction = 3 // Replace this with your client-to-client command
    }

    // Envelope for all messages handled by the server
    public class Message
    {
        public string ClientId { get; set; }
        public Command Command { get; set; }
        public string Data { get; set; }
    }

    // Command for seding a message from one client to antoher.   
    // This would be serialized as JSON and stored in the 'Data' member of the Message object.
    public class SendToClientCommand
    {
        public string DestinationClientId { get; set; }  // The client to receive the message

        public Command ClientCommand { get; set; } // The command for the destination client to execute

        public string Data { get; set; } // The payload for the destination client
    }

    // An object for storing unhandled messages in a queue to be processed asynchronously
    // This allows us to process messages and respond to the appropriate client,
    // without having to do everything in the ChannelRead0 method and block the main thread
    public class UnhandledMessage
    {
        private readonly Message message;
        private readonly IChannelHandlerContext context;

        public UnhandledMessage(Message message, IChannelHandlerContext context)
        {
            this.message = message;
            this.context = context;
        }

        public Message Message => message;
        public IChannelHandlerContext Context => context;

        public Command Command => message.Command;
        public string ClientId => message.ClientId;
        public string Data => message.Data;
    }

    // A representation of the connected Clients on the server.  
    // Note:  This is not the 'Client' class that would be used to communicate with the server.
    public class Client
    {
        private readonly string clientId;
        private readonly IChannelHandlerContext context;

        public Client(string clientId, IChannelHandlerContext context)
        {
            this.clientId = clientId;
            this.context = context;
        }

        public string ClientId => clientId;
        public IChannelHandlerContext Context => context;
    }

    // The socket server, using DotNetty's SimpleChannelInboundHandler
    // The ChannelRead0 method is called for each Message received
    public class Server : SimpleChannelInboundHandler<Message>, IDisposable
    {
        private readonly ConcurrentDictionary<string, Client> clients;
        private readonly ConcurrentQueue<UnhandledMessage> unhandledMessages;
        private readonly CancellationTokenSource cancellation;
        private readonly AutoResetEvent newMessage;

        public Server(CancellationToken cancellation)
        {
            this.clients = new ConcurrentDictionary<string, Client>();
            this.newMessage = new AutoResetEvent(false);
            this.cancellation = CancellationTokenSource.CreateLinkedTokenSource(cancellation);
        }

        // The start method should be called when the server is bound to a port.
        // Messages will be received, but will not be processed unless/until the Start method is called
        public Task Start()
        {
            // Start a dedicated thread to process messages so that the ChannelRead operation does not block
            return Task.Run(() =>
            {
                var serializer = JsonSerializer.CreateDefault();  // This will be used to deserialize the Data member of the messages

                while (!cancellation.IsCancellationRequested)
                {
                    UnhandledMessage message;
                    var messageEnqueued = newMessage.WaitOne(100);  // Sleep until a new message arrives

                    while (unhandledMessages.TryDequeue(out message))  // Process each message in the queue, then sleep until new messages arrive
                    {
                        if (message != null)
                        {
                            // Note: This part could be sent to the thread pool if you want to process messages in parallel
                            switch (message.Command)
                            {
                                case Command.Register:
                                    // Register a new client, or update an existing client with a new Context
                                    var client = new Client(message.ClientId, message.Context);
                                    clients.AddOrUpdate(message.ClientId, client, (_,__) => client);
                                    break;
                                case Command.SendToClient:
                                    Client destinationClient;
                                    using (var reader = new JsonTextReader(new StringReader(message.Data)))
                                    {
                                        var sendToClientCommand = serializer.Deserialize<SendToClientCommand>(reader);
                                        if (clients.TryGetValue(sendToClientCommand.DestinationClientId, out destinationClient))
                                        {
                                            var clientMessage = new Message { ClientId = message.ClientId, Command = sendToClientCommand.ClientCommand, Data = sendToClientCommand.Data };
                                            destinationClient.Context.Channel.WriteAndFlushAsync(clientMessage);
                                        }
                                    }
                                    break;
                            }
                        }
                    }
                }
            }, cancellation.Token);
        }

        // Receive each message from the clients and enqueue them to be procesed by the dedicated thread
        protected override void ChannelRead0(IChannelHandlerContext context, Message message)
        {
            unhandledMessages.Enqueue(new UnhandledMessage(message, context));
            newMessage.Set(); // Trigger an event so that the thread processing messages wakes up when a new message arrives
        }

        // Flush the channel once the Read operation has completed
        public override void ChannelReadComplete(IChannelHandlerContext context)
        {
            context.Flush();
            base.ChannelReadComplete(context);
        }

        // Automatically stop the message-processing thread when this object is disposed
        public void Dispose()
        {
            cancellation.Cancel();
        }
    }
}
List<Socket> clients = new List<Socket>();
public void AcceptCallback(IAsyncResult ar)
    {
        // Signal the main thread to continue.  
        allDone.Set();

        // Get the socket that handles the client request.  
        Socket listener = (Socket)ar.AsyncState;
        Socket handler = listener.EndAccept(ar);

        clients.Add(handler);
        ...
    }
 public void SendToOne(string id,string message)
    {
        foreach (Socket s in clients)
        {
            if (s.Handle.ToString() == id)
            {
                Send(s, message);
            }
        }

    }