C#使用TCP和UDP协议

4
我需要在我的应用程序中使用UDP和TCP连接,TcpClient/TcpListener很少被使用,但UDP则是主要的使用方式。
以下是服务器端代码:
    static void Main(string[] args)
    {
        TcpListener  listener = new TcpListener(IPAddress.Any, 25655);
        listener.Start();
        Socket  sck = listener.AcceptTcpClient().Client;
        UdpClient udpServer = new UdpClient(1100);
        IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
        var data = udpServer.Receive(ref remoteEP);
        string result = Encoding.UTF8.GetString(data);
        Console.WriteLine(result);
        Console.Read();
    }

这是客户端:

   static void Main(string[] args)
    {
       TcpClient client = new TcpClient("127.0.0.1", 25655);
       Socket sck = client.Client;
       UdpClient udpclient = new UdpClient();
       IPEndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1100); // endpoint where server is listening
       udpclient.Connect(ep);
       byte[] data = UTF8Encoding.UTF8.GetBytes("Hello");
       udpclient.Send(data,data.Length);       
    }

我首先建立了Tcp连接,然后尝试从客户端向服务器发送数据。通过我添加的断点,我可以看到Tcp部分正常工作,客户端完成程序,但在服务器上,它在接收部分卡住了,就像没有数据到达一样。当我删除服务器和客户端中的tcp代码部分(前两行)时,它能够正常工作并显示结果消息。
有人知道为什么我无法从客户端获取数据吗?
提前感谢。

虽然我没有直接回答你的问题,但我想让你知道WCF,它使得使用Tcp和其他消息标准变得非常容易。https://msdn.microsoft.com/en-us/library/ee354381.aspx - Matt Hensley
3个回答

1
TCP和UDP的主要区别在于,TCP会尝试重新发送消息,直到服务器告诉客户端已经收到为止。而即使数据包未到达或主机根本不存在,UDP也会发送并忘记它。
以下是您代码的流程:
服务器启动TCP
客户端发送TCP
服务器接收TCP
客户端发送UDP(服务器尚未监听,数据包丢失但UDP不关心)
服务器开始监听UDP
服务器等待UDP到来 <--- 挂起
您希望进行一些多线程编程,并在尝试从客户端发送消息之前同时启动它们。

你的意思是客户端在服务器开始接收数据之前发送了数据吗?所以,如果我在发送部分(客户端代码中)使用 Thread.Sleep();,我就能够在服务器端读取消息了吗? - Slashy
@Slashy 你应该这样做。 - Steve

1

问题在于listener.AcceptTcpClient()阻塞了当前线程,而且在创建Tcp连接之前服务器端的UdpClient还未建立。事实上,你的服务器正在等待Tcp连接,只有在此之后才开始监听Udp连接,而你的客户端则是依次创建2个连接。我的建议是-在客户端实际发送数据后,服务器开始监听Udp端口。检查我的建议最简单的方法是-对于客户端代码,在通过UDP发送数据之前添加Thread.Sleep(1000)。为了使其正常工作,您可能需要修改代码,将Tcp和Udp分开处理,类似于以下方式:

static void Main(string[] args)
{
    Task.Factory.StartNew(() => 
    {
        TcpListener listener = new TcpListener(IPAddress.Any, 25655);
        listener.Start();
        Socket sck = listener.AcceptTcpClient().Client;

        // ToDo: further actions related to TCP client
    }, TaskCreationOptions.LongRunning);

    UdpClient udpServer = new UdpClient(1100);
    IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
    var data = udpServer.Receive(ref remoteEP);
    string result = Encoding.UTF8.GetString(data);
    Console.WriteLine(result);
    Console.Read();
}

客户端代码在这个例子中可能可以保持不变,但是对于真实的项目,我建议也将其分开,因为你肯定想通过Tcp从服务器获取一些数据。

0
如果您先在服务器端启动UDP客户端,然后再在客户端和服务器之间建立TCP连接,会发生什么?!
服务器
        static void Main(string[] args)
    {
        UdpClient udpServer = new UdpClient(1100);
        IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);

        TcpListener listener = new TcpListener(IPAddress.Any, 25655);
        listener.Start();
        Socket sck = listener.AcceptTcpClient().Client;

        var data = udpServer.Receive(ref remoteEP);
        string result = Encoding.UTF8.GetString(data);
        Console.WriteLine(result);
        Console.Read();
    }

客户端

static void Main(string[] args)
{
    TcpClient client = new TcpClient();
    client.Connect("127.0.0.1", 25655);

    UdpClient udpclient = new UdpClient();
    IPEndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1100); // endpoint where server is listening
    udpclient.Connect(ep);
    byte[] data = UTF8Encoding.UTF8.GetBytes("Hello");
    udpclient.Send(data, data.Length);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接