Я пишу приложение Metro в Windows 8 Consumer Preview.
Однако я не могу использовать TcpClient в .NET 4.5, кажется, нет места для добавления ссылки на сборку.
http://msdn.microsoft.com/en-us/library/1612451t(v=vs.110).aspx
Я пишу приложение Metro в Windows 8 Consumer Preview.
Однако я не могу использовать TcpClient в .NET 4.5, кажется, нет места для добавления ссылки на сборку.
http://msdn.microsoft.com/en-us/library/1612451t(v=vs.110).aspx
TcpClient не поддерживается на стороне метро. Вы можете использовать класс StreamSocket. вместо. здесь приведен пример того, как использовать его для создания TCP-сокета, создания подключение, отправка и получение данных. Примеры представлены в JS и C++, но тот же класс будет работать и в C#.
В конце концов, нам, вероятно, следует использовать новый материал 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 так, как хочет Microsoft. Это просто расстраивает, когда они продолжают менять румяный фреймворк. (Если Xamarin может поддерживать согласованные фреймворки на iOS/Android/и т. д., почему MS не может работать на своих собственных ОС!)