如何在Windows 8 Consumer Preview中使用TcpClient

时间:2012-03-05 17:40:16

标签: windows windows-8 .net-4.5

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

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

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

2 个答案:

答案 0 :(得分:3)

地铁方面不支持TcpClient。您可以改用StreamSocket课程。 Here是关于如何使用它来创建TCP套接字,建立连接,发送和接收数据的示例。样本使用JS和C ++,但同一个类适用于C#。

答案 1 :(得分:1)

最终,我们应该使用新的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 /等上保持一致的框架,为什么MS不能在自己的OS上运行!)