J'ai décidé de mettre en œuvre une implémentation client-serveur-client simple utilisant le multithreading. Le problème que j'ai rencontré est que chaque deuxième message envoyé du client A au client B revient au client A. Je ne suis pas tout à fait sûr de pourquoi cela se produit. Ma supposition éclairée est la combinaison du multithreading et de l'IPEndPoint de l'expéditeur passé par référence, cependant je ne vois vraiment aucun moyen de contourner cette référence. Voici des extraits de code :
Code serveur :
using System;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace UDP
{
public sealed class UdpServer
{
public static void Main()
{
var ipEndPoint = new IPEndPoint(IPAddress.Loopback, 12345);
var udpServer = new UdpClient(ipEndPoint);
var clientOne = new IPEndPoint(IPAddress.Loopback, 12346);
var clientTwo = new IPEndPoint(IPAddress.Loopback, 12347);
var taskFactory = new TaskFactory();
var tokenSource = new CancellationTokenSource();
var cancellationToken = tokenSource.Token;
var taskArray = new Task[2];
taskArray[0] = taskFactory.StartNew(() => MessagingTask(udpServer, clientOne, clientTwo, tokenSource, cancellationToken), cancellationToken);
taskArray[1] = taskFactory.StartNew(() => MessagingTask(udpServer, clientTwo, clientOne, tokenSource, cancellationToken), cancellationToken);
Task.WaitAny(taskArray);
}
private static void MessagingTask(UdpClient udpServer, IPEndPoint sender, IPEndPoint receiver, CancellationTokenSource tokenSource, CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
var bytes = udpServer.Receive(ref sender);
var message = Encoding.ASCII.GetString(bytes, 0, bytes.Length);
Console.WriteLine($"IP: {sender.Address} Port: {sender.Port}, {DateTime.Now}: {message}");
udpServer.Send(bytes, bytes.Length, receiver);
Console.WriteLine($"Send to: {receiver.Address} Port: {receiver.Port}, {DateTime.Now}: {message}");
}
}
}
}
Code client :
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace UDP
{
public sealed class UdpClientOne
{
public static void Main()
{
var clientEndpoint = new IPEndPoint(IPAddress.Loopback, 12346);
var serverEndpoint = new IPEndPoint(IPAddress.Loopback, 12345);
var udpClient = new UdpClient(clientEndpoint);
var taskFactory = new TaskFactory();
var tokenSource = new CancellationTokenSource();
var cancellationToken = tokenSource.Token;
var taskArray = new Task[2];
taskArray[0] = taskFactory.StartNew(() => ReadingThread(udpClient, serverEndpoint, cancellationToken), cancellationToken);
taskArray[1] = taskFactory.StartNew(() => SendingThread(udpClient, serverEndpoint, tokenSource, cancellationToken), cancellationToken);
Task.WaitAny(taskArray);
udpClient.Close();
}
private static void ReadingThread(UdpClient udpClient, IPEndPoint ipEndPoint, CancellationToken cancellationToken)
{
while (true)
{
if (cancellationToken.IsCancellationRequested)
{
Console.WriteLine("Fermeture de l'application...");
return;
}
var data = udpClient.Receive(ref ipEndPoint);
var message= Encoding.ASCII.GetString(data, 0, data.Length);
Console.WriteLine($"{DateTime.Now}: {message}");
}
}
private static void SendingThread(UdpClient udpClient, IPEndPoint ipEndPoint, CancellationTokenSource tokenSource, CancellationToken cancellationToken)
{
string userInput = "";
while (true)
{
userInput = Console.ReadLine();
if (string.IsNullOrEmpty(userInput))
continue;
if (userInput.Equals("q"))
{
Console.WriteLine("Fermeture de l'application...");
tokenSource.Cancel();
}
var bytes = Encoding.ASCII.GetBytes(userInput);
udpClient.Send(bytes, bytes.Length, ipEndPoint);
}
}
}
}
Sortie dans la console :