[SOLVED] Określenie ilości danych w NetworkStream

0

Mam sobie taką funkcję do czytania danych z NetworkStream

/// <summary> /// Reads data from network stream /// </summary> /// <param name="ns">NetworkStream from which data is to be read </param> /// <returns>data read from NetworkStream</returns> #region ReadBuffer private string ReadBuffer(NetworkStream ns) { byte[] buffer = new byte[1024]; int i = 0; int b; int timeout = System.Environment.TickCount;
        try
        {
            // wait for data to show up on the stream
            while (!ns.DataAvailable && ((System.Environment.TickCount - timeout) < 20000))
            {
                System.Threading.Thread.Sleep(100);
            }
            if (!ns.DataAvailable)
            {
                //throw new Exception("No response received from server.");
                AddLogMessage("No response received from server.");
            }

            // read while there's data on the stream
            while (i < buffer.Length && ns.DataAvailable)
            {
                b = ns.ReadByte();
                buffer[i++] = (byte)b;
            }
        }
        catch (System.IO.IOException)
        {
            // error reading from stream
            //throw new Exception("Error receiving data from server.");
            AddLogMessage("Error receiving data from server.");
        }

        return Encoding.ASCII.GetString(buffer);
    }
    #endregion

i wszystko jest fajnie jeśli dane nie przekraczają wartości 1024 bajtów (byte[] buffer = new byte[1024];). Ale jeśli chcę odczytać coś większego - np: treść maila pobieranego z serwera - to on już przekracza 1024 bajty i dostaje tylko kawałem zawartości. Pomyślałem sobie, że można dynamicznie sprawdzać rozmiar danych po tym jak trafiłem na pole Lenght. Pogmerałem w necie i znalazłem f-cję do zmiany rozmiaru tablicy bajtów:

<code class="c#">
		public byte [] ReDim(byte [] array, int newSize)
		{
			byte [] abytNew = new byte[newSize];
			Buffer.BlockCopy(array, 0, abytNew, 0, newSize);
			return abytNew;
		}

i odpowiednio zmodyfikowałem kod f-cji ReadBuffer:

#region ReadBuffer
/// <summary>
/// Reads data from network stream
/// </summary>
/// <param name="ns">NetworkStream from which data is to be read </param>
/// <returns>data read from NetworkStream</returns>
private string ReadBuffer(NetworkStream ns)
{
byte[] buffer = new byte[1024];
int i = 0;

        int b;
        int timeout = System.Environment.TickCount;

        try
        {
            // wait for data to show up on the stream
            while (!ns.DataAvailable && ((System.Environment.TickCount - timeout) < 20000))
            {
                System.Threading.Thread.Sleep(100);
            }
            if (!ns.DataAvailable)
            {
                //throw new Exception("No response received from server.");
                AddLogMessage("No response received from server.");
            }

            // read while there's data on the stream
            while (i < buffer.Length && ns.DataAvailable)
            {
            	if (ns.Length >= buffer.Length)
            	{
            		buffer = ReDim(buffer, (int)ns.Length);
            	}
                b = ns.ReadByte();
                buffer[i++] = (byte)b;
            }
        }
        catch (System.IO.IOException)
        {
            // error reading from stream
            //throw new Exception("Error receiving data from server.");
            AddLogMessage("Error receiving data from server.");
        }

        return Encoding.ASCII.GetString(buffer);
    }
    #endregion

Kompilacja przechodzi gładko (beż żadnych błędów czy ostrzeżeń). Ale w czasie wykonywania program rzuca takim wyjątkiem:


> System.NotSupportedException: Ten strumień nie obsługuje operacji szukania.
>    at System.Net.Sockets.NetworkStream.get_Length
>    at Emilia.MainForm.ReadBuffer in f:\Projects\Emilia.NET\Emilia\MainForm.cs:line 112
>    at Emilia.MainForm.Button1Click in f:\Projects\Emilia.NET\Emilia\MainForm.cs:line 167
>    at System.Windows.Forms.Control.OnClick
>    at System.Windows.Forms.Button.OnClick
>    at System.Windows.Forms.Button.OnMouseUp
>    at System.Windows.Forms.Control.WmMouseUp
>    at System.Windows.Forms.Control.WndProc
>    at System.Windows.Forms.ButtonBase.WndProc
>    at System.Windows.Forms.Button.WndProc
>    at ControlNativeWindow.OnMessage
>    at ControlNativeWindow.WndProc
>    at System.Windows.Forms.NativeWindow.DebuggableCallback
>    at ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop
>    at ThreadContext.RunMessageLoopInner
>    at ThreadContext.RunMessageLoop
>    at System.Windows.Forms.Application.Run
>    at Emilia.Program.Main in f:\Projects\Emilia.NET\Emilia\Program.cs:line 37


Czyli wychodzi na to, że nie można zdefiniować ile danych zawiera ten strumień... Może mi ktoś podpowiedzieć jak to zrealizować ?
0

A nie lepiej użyć Listy?

0

List<byte> będzie tutaj najlepszym rozwiązaniem... Z początku nie skojarzyłem o jakiej liście była mowa i zastanawiałem się nad ArrayList ___
Teraz całość wygląda tak i jak na razie działa:

#region ReadBuffer
/// <summary>
/// Reads data from network stream
/// </summary>
/// <param name="ns">NetworkStream from which data is to be read </param>
/// <returns>data read from NetworkStream</returns>
private string ReadBuffer(NetworkStream ns)
{
List<byte> buffer = new List<byte>;
int b;
int timeout = System.Environment.TickCount;

        try
        {
            // wait for data to show up on the stream
            while (!ns.DataAvailable && ((System.Environment.TickCount - timeout) < 20000))
            {
                System.Threading.Thread.Sleep(100);
            }
            if (!ns.DataAvailable)
            {
                //throw new Exception("No response received from server.");
                AddLogMessage("No response received from server.");
            }

            // read while there's data on the stream
            while (ns.DataAvailable)
            {
                b = ns.ReadByte();
                buffer.Add((byte)b);
            }
        }
        catch (System.IO.IOException)
        {
            // error reading from stream
            //throw new Exception("Error receiving data from server.");
            AddLogMessage("Error receiving data from server.");
        }

        return Encoding.ASCII.GetString(buffer.ToArray());
    }
    #endregion

1 użytkowników online, w tym zalogowanych: 0, gości: 1