1

I have been trying to create a metro application but there is a problem: StreamSocket doesn't really do what I want to do (I think)

Here is an excerpt my code from .Net that works:

        try
        {
            TCP = new TcpClient(server, port);
            Stream = TCP.GetStream();
            Read = new StreamReader(Stream);
            Write = new StreamWriter(Stream);
        }
        catch (Exception e)
        {
            Console.WriteLine("Error connecting to " + server + ": " + e);
            return;
        }

        // Identify
        Write.WriteLine("LOGIN " + Username);
        Write.Flush();

        while (Connected)
        {
            try
            {
                if ((line = Read.ReadLine()) != null && Connected)

I can't get StreamSocket to work... it requires you to know the length of the string that's coming in and I don't know what it will be - it varies. Is there any way to do this that will work?

This is what I have but it doesn't work:

        try
        {
            // Connect to the server (in our case the listener we created in previous step).
            await Socket.ConnectAsync(new HostName("example.com"), "1111");
        }
        catch (Exception exception)
        {
            // If this is an unknown status it means that the error is fatal and retry will likely fail.
            if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown)
            {
                throw;
            }
        }

        // Create a DataWriter if we did not create one yet. Otherwise use one that is already cached.
        Writer = new DataWriter(Socket.OutputStream);
        Listener = new DataReader(Socket.InputStream);

        Debug.WriteLine(Socket.Information.RemoteAddress.CanonicalName); //Check if IP is correct

        SendRaw("LOGIN " + Nickname);

        string line = "";
        Connected = true;
        while (Connected)
        {
            if (Listener.UnconsumedBufferLength != 0)
            {
                line = Listener.ReadString(Listener.UnconsumedBufferLength);
                Debug.WriteLine(line);
            }
        }
    }

    async public void SendRaw(string str)
    {
        Writer.WriteString(str);

        // Write the locally buffered data to the network.
        try
        {
            await Writer.StoreAsync();
        }
        catch (Exception exception)
        {
            // If this is an unknown status it means that the error if fatal and retry will likely fail.
            if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown)
            {
                throw;
            }
        }
    }

Any help would be appreciated!

4

1 回答 1

2

首先要做的事情是:您的原始代码是等待发生的 DOS 攻击。如果可能的话,我建议更改协议以在每个字符串之前包含一个长度前缀,这样您就可以在为其分配内存之前知道它有多大。

第二件事:DataReader类必须先将一些字节读入其内部缓冲区,然后才能解释它们。你通过调用读入这个缓冲区LoadAsync

但是,如果您想读取任意长度的字符串,则必须读取缓冲区并自己扫描换行符,如果未找到换行符,则根据需要调整缓冲区大小(或添加新缓冲区),最多一些最大尺寸。

更新:

设置InputStreamOptionsPartial; 您可以LoadAsync使用任意大的缓冲区大小(例如 1024)调用。获取数据后,调用ReadString(UnconsumedBufferLength). 每次执行此操作时,您可能会得到一行、一行或多行的一部分。因此,您必须先构建 astring然后Splitby \n,并将任何部分行保留在末尾,以便下次通过循环。

于 2012-07-03T09:59:28.270 回答