我必須讓多個客戶端與服務器通信,服務器選擇回復誰。就好像客戶端發送訊息的唯一目的地是服務器。服務器選擇與誰交談。
關鍵是我不知道如何首先創建多個客戶端并將訊息定向到我想要的任何客戶端。
我只需要做一對一。客戶端和服務器。
另外我不知道我是否必須使用很多執行緒,因為我需要一個執行緒來監聽新客戶端的所有連接,另一個執行緒來監聽他們發送給我的內容,從而能夠發送。
在那里我留下我的代碼。
對不起我的英語。使用谷歌翻譯。
西班牙語:Tengo que hacer que varios clientes se comuniquen con el servidor,y el servidor elige a quién responder。Es como si el único destino del cliente para enviar el mensaje fuera el servidor。Y el servidor elige con quién hablar。
El punto es que no sé cómo hacer varios clientes primeo y dirigir los mensajes a cualquiera de esos clientes que quiero。
Solo tengo que hacer un 1 a 1. Cliente y servidor。
Además no sé si tendré que usar muchos hilos, ya que necesitaría un hilo para escuchar todas las conexiones de los nuevos clientes, otro hilo para escuchar lo que me envían y así poder envirar。
Ahí les dejo mi código。
服務器/服務器
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();
}
}
}
uj5u.com熱心網友回復:
您可以使用 TCP/IP 與使用多個客戶端的服務器通信
檢查這個問題和答案服務器客戶端發送/接收簡單的文本
您不需要處理執行緒和任務,因為 .NET TCP 類會為您處理這些。
請注意,在 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();
}
uj5u.com熱心網友回復:
不要使用任何低級 Socket 庫,例如TcpListener或System.Net.Sockets除非您正在嘗試學習套接字編程或進行學校專案。有大量支持良好的 .NET 庫用于進行客戶端-服務器通信,這些庫為您處理低級套接字和多執行緒,因此您可以專注于您的業務規則。
最終的服務器會在 IIS 上運行嗎?如果是,請考慮使用SignalR。它支持客戶端和服務器,并在服務器端具有高級用戶管理,因此服務器可以根據自定義標準向單個客戶端或整個組發送回復或資料。
如果您不能使用 IIS,請嘗試NetCoreServer,它具有異步客戶端和服務器功能,并有使用 TCP、UDP、HTTP 和 WebSockets 的示例。
還有多個其他庫需要考慮。如果您決定使用套接字,請查看此答案中的串列。
更新
由于這是針對需要套接字編程的學校專案,因此您可以執行以下操作。
服務器
- 使用像 a 一樣安全的集合
ConcurrectDictionary來存盤連接的客戶端 - 每個客戶端物件將用于
events從其客戶端接收資料以及檢測客戶端斷開連接 - 服務器將訂閱這些事件并在收到訊息時執行所需的任何操作
- 當服務器執行任何客戶端操作時,如發送訊息,它需要
lock避免死鎖的操作 - 當客戶端斷開連接時,請確保取消訂閱該客戶端的任何訂閱以避免記憶體泄漏
- 這是一個很好的例子
客戶
- 可以使用
TCPClient或簡單Socket和SocketAsyncEventArgs - 您可以查看
SocketAsyncEventArgs以檢查操作何時完成 - 您可以使用異步套接字,因此您無需手動執行執行緒
- 這是一個很好的例子,這是另一個
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/328765.html
上一篇:當我嘗試在GitPod中實體化IMAP4()物件時,為什么Pythonimaplib回傳Errno111:連接被拒絕?
