服务器客户端 send/receive 多个客户端

Server Client send/receive multiple clients

我要让多个客户端与服务器通信,由服务器选择回复谁。这就好像客户端发送消息的唯一目的地是服务器。 服务器选择与谁交谈。

关键是我不知道如何先建立多个客户端并将消息定向到我想要的任何客户端。

我刚要做一对一。客户端和服务器。

我也不知道我是否必须使用很多线程,因为我需要一个线程来监听新客户端的所有连接,另一个线程来监听他们发送给我的内容,从而能够发送。

我留下我的代码。

服务器

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

namespace Servidor_Chat
{
    class Server
    {
        IPAddress ipAddr;
        IPEndPoint endPoint;
        Socket s_Server;
        Socket s_Client;
        public Server()
        {
            ipAddr = IPAddress.Any;
            endPoint = new IPEndPoint(ipAddr, 1234);
            s_Server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            s_Server.Bind(endPoint);
            s_Server.Listen(1);
        } 

        public void Start()
        {
            Console.WriteLine("Esperando clientes...");
            s_Client = s_Server.Accept();
            Console.WriteLine("Un cliente se ha conectado.");
            IPEndPoint clientep = (IPEndPoint)s_Client.RemoteEndPoint;
            Console.WriteLine("Conectado con {0} en el puerto {1}", clientep.Address, clientep.Port);
        }

        public void Send(string msg)
        {
            string texto = "";
            byte[] textoAEnviar;
            texto = msg;
            textoAEnviar = Encoding.Default.GetBytes(texto);
            s_Client.Send(textoAEnviar, 0, textoAEnviar.Length, 0);
        } 

        public void Receive()
        {
            while (true)
            {
                Thread.Sleep(500);
                byte[] ByRec;
                string textoRecibido = "";
                ByRec = new byte[255];
                int a = s_Client.Receive(ByRec, 0, ByRec.Length, 0);
                Array.Resize(ref ByRec, a);
                textoRecibido = Encoding.Default.GetString(ByRec);
                Console.WriteLine("Client: " + textoRecibido);
                Console.Out.Flush();
            }
        }
    } 

    class Program
    {
        static void Main(string[] args)
        {
            Thread t;
            Server s = new Server();
            s.Start();
            t = new Thread(new ThreadStart(s.Receive));
            t.Start();
            while (true)
            {
                s.Send(Console.ReadLine());
            } 

            Console.WriteLine("Presione cualquier tecla para terminar");
            Console.ReadLine();
        }
    }
}

客户

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

namespace Cliente_Chat
{
    class Program
    {
        class Client
        {
            IPAddress ipAddr;
            IPEndPoint endPoint;
            Socket s_Client;
            public Client()
            {
                ipAddr = IPAddress.Parse("127.0.0.1");
                endPoint = new IPEndPoint(ipAddr, 1234);
                s_Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            } 

            public void Start()
            {
                try
                {
                    s_Client.Connect(endPoint);
                    Console.WriteLine("Conectado con exito");
                }
                catch (SocketException e)
                {
                    Console.WriteLine("No se pudo conectar al servidor");
                    Console.WriteLine(e.ToString());
                    return;
                }
            } 

            public void Send(string msg)
            {
                string texto = "";
                byte[] textoAEnviar;
                texto = msg;
                textoAEnviar = Encoding.Default.GetBytes(texto);
                s_Client.Send(textoAEnviar, 0, textoAEnviar.Length, 0);
            } 

            public void Receive()
            {
                while (true)
                {
                    Thread.Sleep(500);
                    byte[] ByRec;
                    string textoRecibido = "";
                    ByRec = new byte[255];
                    int a = s_Client.Receive(ByRec, 0, ByRec.Length, 0);
                    Array.Resize(ref ByRec, a);
                    textoRecibido = Encoding.Default.GetString(ByRec);
                    Console.WriteLine("Server: " + textoRecibido);
                    Console.Out.Flush();
                }
            }
        } 

        static void Main(string[] args)
        {
            Thread t;
            Client c = new Client();
            c.Start();
            t = new Thread(new ThreadStart(c.Receive));
            t.Start();
            while (true)
            {
                c.Send(Console.ReadLine());
            } 

            Console.WriteLine("Presione cualquier tecla para terminar");
            Console.ReadLine();
        }
    }
}

您可以使用 TCP/IP 使用多个客户端与服务器通信

检查这个问题和答案Server Client send/receive simple text

您不需要处理线程和任务,因为 .NET TCP classis 会为您处理。

请注意,在 TCP 侦听器代码中,您必须在 while 循环中执行此操作以保持侦听器正常运行 运行:

 static void Main(string[] args)
{
    //---listen at the specified IP and port no.---
    IPAddress localAdd = IPAddress.Parse(SERVER_IP);
    TcpListener listener = new TcpListener(localAdd, PORT_NO);
    Console.WriteLine("Listening...");
    listener.Start();
    while (true)
    {
        //---incoming client connected---
        TcpClient client = listener.AcceptTcpClient();

        //---get the incoming data through a network stream---
        NetworkStream nwStream = client.GetStream();
        byte[] buffer = new byte[client.ReceiveBufferSize];

        //---read incoming stream---
        int bytesRead = nwStream.Read(buffer, 0, client.ReceiveBufferSize);

        //---convert the data received into a string---
        string dataReceived = Encoding.ASCII.GetString(buffer, 0, bytesRead);
        Console.WriteLine("Received : " + dataReceived);

        //---write back the text to the client---
        Console.WriteLine("Sending back : " + dataReceived);
        nwStream.Write(buffer, 0, bytesRead);
        client.Close();
    }
    listener.Stop();
    Console.ReadLine();
}

不要使用任何低级套接字库,如 TcpListenerSystem.Net.Sockets,除非你正在尝试学习套接字编程或做学校项目。有许多支持良好的 .NET 库可用于执行客户端-服务器通信,为您处理低级套接字和多线程,因此您可以专注于业务规则。

请问最后服务器运行放在IIS上?如果是,请考虑使用 SignalR。它同时支持客户端和服务器,并在服务器端进行高级用户管理,因此服务器可以根据自定义标准向单个客户端或整个组发送回复或数据。

如果您不能使用 IIS,请尝试 NetCoreServer,它具有异步客户端和服务器功能,并有使用 TCP、UDP、HTTP 和 WebSocket 的示例。

还有多个其他库需要考虑。如果您决定使用套接字,请查看此 answer.

中的列表

更新

由于这是一个要求套接字编程的学校项目,您可以执行以下操作。

服务器

  • 使用像 ConcurrectDictionary 这样的安全集合来存储连接的客户端
  • 每个客户端对象将使用 events 从其客户端接收数据并检测客户端断开连接
  • 服务器会订阅这些事件,并在收到消息时做任何它需要的事情
  • 服务器在客户端做任何发送消息等操作时,需要lock操作避免死锁
  • 当客户端断开连接时,确保取消订阅此客户端的任何订阅以避免内存泄漏
  • 这里不错example

客户端

  • 可以使用 TCPClient 或普通 SocketSocketAsyncEventArgs
  • 您可以查看 SocketAsyncEventArgs 以检查操作何时完成
  • 您可以使用异步套接字,这样您就不需要手动执行线程
  • 这里有个好东西example and here is another