在UDP客户端 - 服务委员会实现中,每个第二个消息都会发送给发送者而不是接收器

发布于 2025-02-01 21:01:57 字数 4348 浏览 1 评论 0原文

我决定利用多线程实现一个简单的客户服务器 - 客户实现。我遇到的问题是,从客户端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:

Console output

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

£噩梦荏苒 2025-02-08 21:01:57

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 the UdpClientOne's server sends data to the Client A and receives data from the Client A as well.

enter image description here

In the picture the blue color represents the UdpServer class and the red color represents the UdpClientOne class. Two arrow pointing to the Server (12345 port), hence it will receive the message two times.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文