【问题标题】:How to use TcpClient in Windows 8 Consumer Preview如何在 Windows 8 Consumer Preview 中使用 TcpClient
【发布时间】:2012-04-27 20:16:30
【问题描述】:

我正在 Windows 8 Consumer Preview 中编写 Metro 应用程序。

但是,我无法在 .NET 4.5 中使用 TcpClient,似乎没有添加程序集引用的地方。

http://msdn.microsoft.com/en-us/library/1612451t(v=vs.110).aspx

【问题讨论】:

    标签: windows windows-8 .net-4.5


    【解决方案1】:

    metro 端不支持 TcpClient。您可以改用 StreamSocket 类。 Here 是一个关于如何使用它来创建 TCP Socket、建立连接、发送和接收数据的示例。示例在 JS 和 C++ 中,但相同的类适用于 C#。

    【讨论】:

      【解决方案2】:

      最终,我们可能应该使用新的 Metro NET 东西。但是,如果移植大量代码并取决于您使用的 TcpClient 成员的数量,那么仅围绕 Metro 对象创建一个有限的实现可能还不错。我想快速将一堆代码快速移植到 Metro 上(只是为了尝试一些东西),所以我拼凑了一些看似可行但肯定不理想的东西。 (您最终会同步一些通常不受欢迎的异步方法。)

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      
      using Windows.Networking;
      using Windows.Networking.Sockets;
      using Windows.Storage.Streams;
      
      namespace MetroNetHelper
      {
      public class IPAddress  // assumes IPv4 currently
      {
          public string IP_String;
          public IPAddress() { }
          public IPAddress(string IP) { IP_String = IP; }
          public static IPAddress Broadcast { get { return new IPAddress("255.255.255.255"); } }
          public static IPAddress Parse(string IP) { return new IPAddress(IP); }
          public static bool TryParse(string V, out IPAddress Addr)
          {
              try
              {
                  Addr = IPAddress.Parse(V);
                  return true;
              }
              catch { Addr = null; return false; }
          }
          public HostName GetHostNameObject() { return new HostName(IP_String); }
          public byte[] GetAddressBytes()
          {
              string[] Fields = IP_String.Split('.');
              byte[] temp = new byte[4];
              for (int i = 0; i < temp.Length; i++) temp[i] = byte.Parse(Fields[i]);
              return temp;
          }
      }
      
      public class IPEndPoint
      {
          public IPAddress Address;
          public int Port;
          public IPEndPoint() { }
          public IPEndPoint(IPAddress Addr, int PortNum)
          {
              Address = Addr; Port = PortNum;
          }
      }
      
      public class NetworkStream
      {
          private DataReader Reader;
          private DataWriter Writer;
      
          public void Set(StreamSocket HostClient)
          {
              Reader = new DataReader(HostClient.InputStream);
              Reader.InputStreamOptions = InputStreamOptions.Partial;
              Writer = new DataWriter(HostClient.OutputStream);
          }
      
          public int Write(byte[] Buffer, int Offset, int Len)
          {
              if (Offset != 0 || Len != Buffer.Length) throw new ArgumentException("Can only write whole byte array");
              Writer.WriteBytes(Buffer);
              Task Tk = Writer.StoreAsync().AsTask();
              Tk.Wait();
              return Buffer.Length;
          }
      
          public int Read(byte[] Buffer, int Offset, int Len)
          {
              if (Offset != 0 || Len != Buffer.Length) throw new ArgumentException("Can only read whole byte array");
              Task<uint> Tk = Reader.LoadAsync((uint)Len).AsTask<uint>();
              Tk.Wait();
              uint Count = Tk.Result;
              for (int i=0;i<Count;i++)
              {
                  Buffer[i] = Reader.ReadByte();
              }
              return (int)Count;
          }
      
          public bool DataAvailable
          {
              get
              {
                  return true; // Read() will still work if no data; could we do read ahead 1 byte to determine?
              }
          }
      }
      
      
      public class TcpClient
      {
          private StreamSocket sock;
      
          public void Connect(IPEndPoint EndPt)
          {
              try
              {
                  sock = new StreamSocket();
                  HostName Hst = EndPt.Address.GetHostNameObject();
                  Task Tsk = sock.ConnectAsync(Hst, EndPt.Port.ToString()).AsTask();
                  Tsk.Wait();
              }
              catch (Exception ex) { MetroHelpers.UnpeelAggregate(ex); }
          }
      
          public void Close()
          {
              sock.Dispose();
              sock = null;
          }
      
          public NetworkStream GetStream()
          {
              var N = new NetworkStream();
              N.Set(sock);
              return N;
          }
      }
      
      public static class MetroHelpers
      {
          public static void UnpeelAggregate(Exception Ex)
          {
              AggregateException Ag_Ex = Ex as AggregateException;
              if (Ag_Ex == null) throw Ex;
              if (Ag_Ex.InnerExceptions.Count > 0)
              {
                  if (Ag_Ex.InnerExceptions.Count == 1) throw Ag_Ex.InnerExceptions[0];
                  StringBuilder Str = new StringBuilder();
                  foreach (Exception X in Ag_Ex.InnerExceptions)
                  {
                      Str.AppendLine(X.Message);
                  }
                  throw new Exception(Str.ToString(), Ag_Ex);
              }
              else throw Ag_Ex;
          }
      }
      } // END NAMESPACE
      

      这只是我早上做的又快又脏的事情。如果它可以帮助任何有想法的人,那就太好了。同样,我们很可能最好按照微软希望我们为 Metro 应用程序开发的方式。当他们不断改变红润的框架时,它只会变得令人沮丧。 (如果 Xamarin 可以在 iOS/Android/etc 上保持一致的框架,为什么不能在自己的操作系统上使用 MS!)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-04-17
        • 2012-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-01
        • 2013-08-08
        相关资源
        最近更新 更多