0

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

下面是接收 data(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个字节,字节数组中的剩余空间保持为空,并且stream.DataAvailable为false

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

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

已编辑

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

   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;
    }
4

2 回答 2

1

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

例子:

这个例子表明你可以阅读一个简单的协议。ReadPacket处理长度+数据消息。所以发送者将首先发送一个包含后面数据长度的 int 值。StartReading 方法读取文件名和文件数据。它将存储高达 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);
}
于 2013-09-13T07:49:31.123 回答
1

因为它是一个流,并且可以部分接收。你确定你总是收到 te 大小为 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.
}

这只是一个例子。。

于 2013-09-02T15:07:28.237 回答