I have to make multiple clients communicate with the server, and the server chooses who to reply to. It is as if the client's only destination to send the message is the server. And the server chooses who to talk to.
The point is that I don't know how to make multiple clients first and direct the messages to any of those clients that I want.
I just got to do a 1 to 1. Client and server.
Also I do not know if I will have to use many threads, since I would need a thread to listen to all the connections of the new clients, another thread to listen to what they send me and thus be able to send.
There I leave my code.
Sorry my English. Use google translator.
Español: 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 primero 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 enviar.
Ahí les dejo mi código.
SERVIDOR / SERVER
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();
}
}
}
CLIENT
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();
}
}
}
CodePudding user response:
You can use TCP/IP to communicate with server using multiple clients
check this question and answers Server Client send/receive simple text
You don't need to deal with threads and tasks since .NET TCP classis takes care of that for you.
Note that in the TCP listener code you must do it in a while loop in order to keep the listener up and running:
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();
}
CodePudding user response:
Do not use any low-level Socket libraries like TcpListener
or System.Net.Sockets
unless you are trying to learn socket programming or doing a school project. There are plenty of well-supported .NET libraries for doing client-server communication that handle low level sockets and multi-threading for you so you can focus on your business rules.
Will the final server run on IIS? If yes, look into using SignalR. It supports both client and server and has advance user management on the server side so the server can send replies or data to individual clients or whole groups based on custom criteria.
If you cannot use IIS, try NetCoreServer, It features async client and server and has examples using TCP, UDP, HTTP, and WebSockets.
There are multiple other libraries to consider. If you do decide to use sockets take a look at the list in this answer.
Update
Since this is for a school project where socket programming is a requirement, you can do the following.
Server
- Use a tread-safe collection like a
ConcurrectDictionary
to store connected clients - Each client object would use
events
to receive data from its client as well as detect a client disconnect - The server would subscribe to those events and do whatever it needs when a message is received
- When the server does any client operation like sending messages, it needs to
lock
the operation to avoid deadlocks - When a client disconnects, make sure to unsubscribe from any subscriptions for this client to avoid memory leaks
- Here is a good example
Client