网络流停留在stream.Read(byte [] byte,int offset,int size)

时间:2013-09-02 14:55:00

标签: c# network-programming networkstream

我要做的是接收从客户端发送的大量字节(大约5MB数据)

以下是接收数据(byte [])的代码

    byte[] receivedBytesRaw = new byte[4000];
 //first, initialize network stream
 NetworkStream stream = client.GetStream();
    //The bytesNeeded is the size of bytes which is a protocol sent by the client side indicating the size of byte which will be sent
    int bytesNeeded = 4000;
    int bytesReceived = 0;
    do
    {
        int bytesRead = stream.Read(receivedBytesRaw, bytesReceived, bytesNeeded - bytesReceived);
        networkValidation.addBytesToList(receivedBytesRaw, ref receivedBytes);
        bytesReceived += bytesRead;
    } while (bytesReceived < bytesNeeded);

但现在我遇到了问题:

每次数据到达时,do while循环第一次循环,返回值(i)为26,然后再次循环,这次,当它转到" i = stream.Read(receivedBytesRaw, 0, receivedBytesRaw.Length);"时,程序似乎在等待对于客户端发送数据并且没有响应,当我检查“receivedBytesRaw”时,数据不完整,只收到前13个字节,字节数组中的剩余空间保持为null,而stream.DataAvailable是假

为什么服务器端收到不完整的数据? 注意:当我尝试发送小数据(字符串)时,没关系

=============================================== ======================

被修改

以下是发送数据的客户端代码:

   private int sendData(byte[] dataSend, string IP, int portNumber)
    {
        TcpClient clientSide = new TcpClient();
        int result = -1;
        try
        {
            clientSide.Connect(IP, portNumber);
        }
        catch (Exception ex)
        {
            return 2;
        }
        NetworkStream netStream = clientSide.GetStream();
        if (netStream.CanWrite)
        {
            byte[] replyMsg = new byte[1024];

            netStream.Write(dataSend, 0, dataSend.Length);
            netStream.Flush();
            result = 0;
        }
        else
        {
            result = 1;
        }
        return result;
    }

2 个答案:

答案 0 :(得分:1)

因为它是一个流,可以部分接收。你确定你总是收到大小为2048字节的软件包吗?

     int i = 0;
     int bytesNeeded = 200;
     int bytesReceived = 0;
     do
      {
        //read byte from client
        int bytesRead = stream.Read(receivedBytesRaw, bytesReceived, bytesNeeded-bytesReceived);
        bytesReceived += bytesRead;
        // merge byte array to another byte array
      } while (bytesReceived < bytesNeeded);

我认为你需要一个帧协议,尝试创建一个类似的协议,写下随后数据的大小。

示例:(伪)

void SendData(byte[] data)
{
    // get the 4 bytes of a int value.
    byte[] dataLength = BitConverter.GetBytes(data.Lenght);
    // write the length to the stream.
    stream.Write(dataLength, 0, dataLength.Length);
    // write the data bytes.
    stream.Write(data, 0, data.Length);
}

void Receive()
{
    // read 4 bytes from the stream.
    ReadBuffer(buffer, 4);
    // convert those 4 bytes to an int.
    int dataLength = BitConverter.ToInt32(buffer, 0);
    // read bytes with dataLength as count.
    ReadBuffer(buffer, dataLength);    
}

// read until the right amount of bytes are read.
void ReadBuffer(byte[] buffer, int length)
{
    int i = 0;
    int bytesNeeded = length;
    int bytesReceived = 0;
    do
    {
        //read byte from client
        int bytesRead = stream.Read(buffer, bytesReceived, bytesNeeded-bytesReceived);
        bytesReceived += bytesRead;
        // merge byte array to another byte array
    } while (bytesReceived < bytesNeeded);   //  <- you should do this async.
}

这只是一个例子..

答案 1 :(得分:1)

您可以尝试的另一种解决方案是使用异步读取。 我创建了一个读取所有字节的类。如果读取完整文件不是问题,可以试试这个:

示例:

此示例显示您可以阅读简单的协议。 ReadPacket处理长度+数据消息。因此发送方将首先发送一个包含后续数据长度的int值。 StartReading方法读取文件名和filedata。它将存储最多10mb的最大文件大小。但这最初并不是为接收文件而设计的。

const int MaxFileSize = 10 * 1024 * 1024;

private void Example()
{
    Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    socket.Connect("localhost", 12345);

    StartReading(socket);
}

private void StartReading(Socket socket)
{
    ReadPacket(socket, (filenameData) =>
    {
        if (filenameData.Count == 0)
        {
            // disconnected
            return;
        }

        // parse the filename
        string filename = Encoding.UTF8.GetString(filenameData.Array, filenameData.Offset, filenameData.Count);
        Trace.WriteLine("Receiving file :" + filename);

        ReadPacket(socket, (fileData) =>
        {
            if (fileData.Count == 0)
            {
                // disconnected
                return;
            }

            Trace.WriteLine("Writing file :" + filename);

            // write to the file
            using (FileStream stream = new FileStream(filename, FileMode.Create, FileAccess.Write))
                stream.Write(fileData.Array, fileData.Offset, fileData.Count);

            // start waiting for another packet.
            StartReading(socket);
        });
    });
}

private void ReadPacket(Socket socket, Action<ArraySegment<byte>> endRead)
{
    // read header. (length of data) (4 bytes)
    EasySocketReader.ReadFromSocket(socket, 4, (headerBufferSegment) =>
    {
        // if the ReadFromSocket returns 0, the socket is closed.
        if (headerBufferSegment.Count == 0)
        {
            // disconnected;
            endRead(new ArraySegment<byte>());
            return;
        }

        // Get the length of the data that follows
        int length = BitConverter.ToInt32(headerBufferSegment.Array, headerBufferSegment.Offset);

        // Check the length
        if (length > MaxFileSize)
        {
            // disconnect
            endRead(new ArraySegment<byte>());
            return;
        }

        // Read bytes specified in length.
        EasySocketReader.ReadFromSocket(socket, length, (dataBufferSegment) =>
        {
            // if the ReadFromSocket returns 0, the socket is closed.
            if (dataBufferSegment.Count == 0)
            {
                endRead(new ArraySegment<byte>());
                return;
            }

            endRead(dataBufferSegment);
        });

    });

}

EasySocketReader课程可以在我的博客上找到:http://csharp.vanlangen.biz/network-programming/async-sockets/asyncsocketreader/

可在此处找到原始的EasyPacketReader:http://csharp.vanlangen.biz/network-programming/async-sockets/easypacketreader/

对于发送部分,您可以使用以下内容:

private void SendFile(Socket socket, string filename)
{
    byte[] filenameData = Encoding.UTF8.GetBytes(filename);
    socket.Send(BitConverter.GetBytes(filenameData.Length));
    socket.Send(filenameData);

    int fileSize;
    byte[] fileData;

    using (FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read))
    {
        fileSize = (int)stream.Length;

        if (fileSize > MaxFileSize)
            throw new ArgumentOutOfRangeException("File too big");

        fileData = new byte[fileSize];

        stream.Read(fileData, 0, fileSize);
    }

    socket.Send(BitConverter.GetBytes(fileSize));
    socket.Send(fileData);
}
相关问题