在UDP客户端 - 服务委员会实现中,每个第二个消息都会发送给发送者而不是接收器
我决定利用多线程实现一个简单的客户服务器 - 客户实现。我遇到的问题是,从客户端A到客户端B发送的每一个消息都回到客户端A。我不确定为什么会发生这种情况。我有根据的猜测是多线程和发件人ipendpoint作为参考的组合,但是我并没有看到任何方法可以解决参考。这是代码的摘要:
服务器代码:
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}");
}
}
}
}
客户端代码:
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("Closing 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("Closing application...");
tokenSource.Cancel();
}
var bytes = Encoding.ASCII.GetBytes(userInput);
udpClient.Send(bytes, bytes.Length, ipEndPoint);
}
}
}
}
控制台输出:
I have decided to implement a simple client-server-client implementation utilizing multithreading. The problem I encountered is that the every second message sent from client A to client B goes back to the client A. I am not entirely sure why is that happening. My educated guess is the combination of multithreading and sender IPEndPoint passed as reference, however I don't really see any way to workaround the reference. Here are snippets of the code:
Server code:
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(quot;IP: {sender.Address} Port: {sender.Port}, {DateTime.Now}: {message}");
udpServer.Send(bytes, bytes.Length, receiver);
Console.WriteLine(quot;Send to: {receiver.Address} Port: {receiver.Port}, {DateTime.Now}: {message}");
}
}
}
}
Client code:
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("Closing application...");
return;
}
var data = udpClient.Receive(ref ipEndPoint);
var message= Encoding.ASCII.GetString(data, 0, data.Length);
Console.WriteLine(quot;{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("Closing application...");
tokenSource.Cancel();
}
var bytes = Encoding.ASCII.GetBytes(userInput);
udpClient.Send(bytes, bytes.Length, ipEndPoint);
}
}
}
}
Console output:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
udpserver
的服务器(端口号: 12345 )正在从客户端接收消息(端口号: 12346 ),然后转发给客户端B(端口号: 12347 )。但是,udpclientone
的服务器 将 数据发送给客户端A和 接收 data也来自客户a。图片中的蓝色表示
udpserver
类,红色代表udpclientone
类。两个指向服务器的箭头( 12345 端口),因此它将两次接收到消息。The
UdpServer
's server (port number: 12345) is receiving the message from Client A (port number: 12346) and then forwarded to Client B (port number: 12347). However theUdpClientOne
's server sends data to the Client A and receives data from the Client A as well.In the picture the blue color represents the
UdpServer
class and the red color represents theUdpClientOne
class. Two arrow pointing to the Server (12345 port), hence it will receive the message two times.