简体   繁体   English

C#套接字(TCP和UDP)

[英]C# Sockets (TCP & UDP)

I'll cut to the point, I've been stuck on this for a few hours now. 我要直言不讳,我已经坚持了几个小时。 Tons of Google and tons of research but not straight answer as of yet. 谷歌的吨和大量的研究,但尚未直接答案。

I have a client and a server coded for TCP which functions perfectly fine, however, I want the client to also be able to use UDP with the server for none-important packets such as player location. 我有一个客户端和一个为TCP编码的服务器,它们运行正常,但是,我希望该客户端也能够将UDP与服务器一起使用,以传输不重要的数据包,例如播放器位置。

As of right now, this is my connect code for connected clients. 截至目前,这是我的已连接客户端的连接代码。

public void ConnectToServer(){
    tcp_client = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
    tcp_client.Connect(server_ip, server_port);
    tcp_stream = new NetworkStream(this.tcp_client);

    this.udp_client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    this.udp_client.BeginConnect(IPAddress.Parse(server_ip), server_port,new AsyncCallback(udp_connected), null);
}

Now the client isn't what I've had issues with for when I use udp.Send(byteArray) it appears to be sending as it's not throwing any exceptions but the server itself isn't responding to any data received. 现在,客户端不是我遇到的问题,因为当我使用udp.Send(byteArray)它似乎正在发送,因为它没有udp.Send(byteArray)任何异常,但是服务器本身没有响应收到的任何数据。

Please Note this is NOT 100% copy/pasted code. 请注意,这不是100%复制/粘贴的代码。 Alter to show just what's being an issue. 更改以仅显示问题所在。

private Socket c;
private UdpClient udp;
private isRunning = true;

public Client(Socket c){
    // This was accepted from TcpListener on Main Server Thread.
    this.c = c;
    this.networkStream = new NetworkStream(this.c);

    udp = new UdpClient();
    udp.Connect((IPEndPoint)c.RemoteEndPoint);

    // Then starts 2 thread for listening, 1 for TCP and 1 for UDP.
}

private void handleUDPTraffic(){
    IPEndPoint groupEP = (IPEndPoint)c.RemoteEndPoint;
    while (isRunning){
        try{
            byte[] udp_received = udp.Receive(ref groupEP);
            Console.WriteLine("Received UDP Packet Data: " + udp_received.Length);
        }catch{
            log.ERROR("UDP", "Couldn't Receive Data...");
        }
    }
}

You can use both TCP and UDP on the same port. 您可以在同一端口上同时使用TCP和UDP。 See also: 也可以看看:

Can TCP and UDP sockets use the same port? TCP和UDP套接字可以使用同一端口吗?

The sample below demonstrates that, you can simultaneously send and receive UDP and TCP messages. 下面的示例演示,您可以同时发送和接收UDP和TCP消息。

Maybe, your UdpClient creation to listen for incoming datagrams is the problem. 也许,您的UdpClient创建用于侦听传入的数据报是问题所在。 I recommend to create it once like your TcpListener. 我建议像TcpListener一样一次创建它。

The servers: 服务器:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace TCPUDPServer
{
  class Program
  {
    static void Main(string[] args)
    {
      TcpListener tcpServer = null;
      UdpClient   udpServer = null;
      int         port      = 59567;

      Console.WriteLine(string.Format("Starting TCP and UDP servers on port {0}...", port));

      try
      {
        udpServer = new UdpClient(port);
        tcpServer = new TcpListener(IPAddress.Any, port);

        var udpThread          = new Thread(new ParameterizedThreadStart(UDPServerProc));
        udpThread.IsBackground = true;
        udpThread.Name         = "UDP server thread";
        udpThread.Start(udpServer);

        var tcpThread          = new Thread(new ParameterizedThreadStart(TCPServerProc));
        tcpThread.IsBackground = true;
        tcpThread.Name         = "TCP server thread";
        tcpThread.Start(tcpServer);

        Console.WriteLine("Press <ENTER> to stop the servers.");
        Console.ReadLine();
      }
      catch (Exception ex)
      {
        Console.WriteLine("Main exception: " + ex);
      }
      finally
      {
        if (udpServer != null)
          udpServer.Close();

        if (tcpServer != null)
          tcpServer.Stop();
      }

      Console.WriteLine("Press <ENTER> to exit.");
      Console.ReadLine();
    }

    private static void UDPServerProc(object arg)
    {
      Console.WriteLine("UDP server thread started");

      try
      {
        UdpClient server = (UdpClient)arg;
        IPEndPoint remoteEP;
        byte[] buffer;

        for(;;)
        {
          remoteEP = null;
          buffer   = server.Receive(ref remoteEP);

          if (buffer != null && buffer.Length > 0)
          {
            Console.WriteLine("UDP: " + Encoding.ASCII.GetString(buffer));
          }
        }
      }
      catch (SocketException ex)
      {
        if(ex.ErrorCode != 10004) // unexpected
          Console.WriteLine("UDPServerProc exception: " + ex);
      }
      catch (Exception ex)
      {
        Console.WriteLine("UDPServerProc exception: " + ex);
      }

      Console.WriteLine("UDP server thread finished");
    }

    private static void TCPServerProc(object arg)
    {
      Console.WriteLine("TCP server thread started");

      try
      {
        TcpListener server = (TcpListener)arg;
        byte[]      buffer = new byte[2048];
        int         count; 

        server.Start();

        for(;;)
        {
          TcpClient client = server.AcceptTcpClient();

          using (var stream = client.GetStream())
          {
            while ((count = stream.Read(buffer, 0, buffer.Length)) != 0)
            {
              Console.WriteLine("TCP: " + Encoding.ASCII.GetString(buffer, 0, count));
            }
          }
          client.Close();
        }
      }
      catch (SocketException ex)
      {
        if (ex.ErrorCode != 10004) // unexpected
          Console.WriteLine("TCPServerProc exception: " + ex);
      }
      catch (Exception ex)
      {
        Console.WriteLine("TCPServerProc exception: " + ex);
      }

      Console.WriteLine("TCP server thread finished");
    }
  }
}

The clients: 客户:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace TCPUDPClient
{
  class Program
  {
    static void Main(string[] args)
    {
      UdpClient      udpClient = null;
      TcpClient      tcpClient = null;
      NetworkStream  tcpStream = null;
      int            port      = 59567;
      ConsoleKeyInfo key;
      bool           run = true;
      byte[]         buffer;

      Console.WriteLine(string.Format("Starting TCP and UDP clients on port {0}...", port));

      try
      {
        udpClient = new UdpClient();
        udpClient.Connect(IPAddress.Loopback, port);

        tcpClient = new TcpClient();
        tcpClient.Connect(IPAddress.Loopback, port);

        while(run)
        {
          Console.WriteLine("Press 'T' for TCP sending, 'U' for UDP sending or 'X' to exit.");
          key = Console.ReadKey(true);

          switch (key.Key)
          {
            case ConsoleKey.X:
              run = false;
              break;

            case ConsoleKey.U:
              buffer = Encoding.ASCII.GetBytes(DateTime.Now.ToString("HH:mm:ss.fff"));
              udpClient.Send(buffer, buffer.Length);
              break;

            case ConsoleKey.T:
              buffer = Encoding.ASCII.GetBytes(DateTime.Now.ToString("HH:mm:ss.fff"));

              if (tcpStream == null)
                tcpStream = tcpClient.GetStream();

              tcpStream.Write(buffer, 0, buffer.Length);
            break;
          }
        }
      }
      catch (Exception ex)
      {
        Console.WriteLine("Main exception: " + ex);
      }
      finally
      { 
        if(udpClient != null)
          udpClient.Close();

        if(tcpStream != null)
          tcpStream.Close();

        if(tcpClient != null)
          tcpClient.Close();
      }

      Console.WriteLine("Press <ENTER> to exit.");
      Console.ReadLine();
    }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM