tcpclient读取的字节数少于预期

时间:2014-10-28 19:51:27

标签: c# byte tcpclient networkstream

我有tcpclient的问题,我需要发送一个或多个文件,所以我有一个服务器和客户端的应用程序,协议是这样的:

1)我发送一些字符串,其中包含有关文件数量,文件名称及其大小的信息,所有这一切都与streamwriter.writeline(从具有该功能的服务器接收) streamreader.readline)

2)在这些字符串之后,我发送文件,在每个文件之后,服务器使用" ACK"的streamwriter.writeline回答客户端。该文件随之发送 networkstream.write方法,并通过networkstream.read接收。

问题是服务器读取直到接收的​​字节数等于文件大小,但是......尽管客户端"似乎"发送文件的每个字节,服务器 总共收到更少的字节!因此,在此步骤中应用程序被阻止,服务器正在等待下一个字节,并且客户端正在等待" ACK" 使用streamreader.readline发送下一个文件或只是为了完成操作。

我还想查看服务器收到的内容,因此我打印了在读取周期中收到的字节数,发现有时服务器读取的字节数少于流的缓冲区大小(固定为1024)。这应该是正常的,因为TCP尽快读取,它应该不是真正的问题,对吧?我不能 相信tcp丢失字节,但我不知道如何解决。

您可以在这里找到代码的一部分:

----服务器端----------

..........Doing Stuffs.............
//secServer is the TCPListener socket.
this.secSHandler = secServer.AcceptTcpClient();
this.secSHandler.ReceiveBufferSize = 1024;
this.secSHandler.SendBufferSize = 1024;

this.is_connected_now = true;

print("is connected!!! ");

//Taking streams...
this.stream = this.secSHandler.GetStream();
this.sr = new StreamReader(stream);
this.sw = new StreamWriter(stream);

string first = sr.ReadLine();
print("I read + " + first + " .");
int numFiles = 0;
string connType = first.Substring(0, 6);
    if (connType.CompareTo("CLIENT") == 0)
    {
    //SINCR CLIENT -> SERVER
    string clipType = first.Substring(7, 4);
        if (clipType.CompareTo("FILE") == 0)
        {
        //CASE RECEIVE FILE

        int posSeparator = first.IndexOf('*');
        string nFiles = first.Substring(12, first.Length - 13);
        numFiles = Convert.ToInt16(nFiles);
        string[] fileNames = new string[numFiles];
        int[] fileSizes = new int[numFiles];

            //TAKE FROM THE CLIENT ALL FILE NAMES AND SIZES
            for (int i = 0; i < numFiles; i++)
            {
            fileNames[i] = sr.ReadLine();
            print("Name file : I read " + fileNames[i]);
            string dim = sr.ReadLine();
            fileSizes[i] = Convert.ToInt32(dim);
            print("Size file : I read " + fileSizes[i]);
            }

            //RECEVING FILES
            for (int i = 0; i < numFiles; i++)
            {
            receive_single_file_1(stream, fileSizes[i], fileNames[i]); //CANNOT GO AFTER THIS POINT
            sw.WriteLine("File sent - number " + i);    
            sw.Flush();
            }
        }
    }   
.............Doing others stuffs.............

sr.Close();
sw.Close();

功能接收单一文件在此以下

public bool receive_single_file_1(NetworkStream netstream, int size, string filename)
{

    int sizeToRead = 0;


    string f_name = "";
    //...f_name is the result of another operation, for the sake of the example i write only the final instruction
    f_name = filename;

    byte[] RecData = new byte[1024];
    int RecBytes = 0;

    try
    {

        int totalrecbytes = 0;
        FileStream Fs = new FileStream((tempFold + f_name), FileMode.OpenOrCreate, FileAccess.Write);
        //COUNTER OF THE WHILE
        int nciclo = 0;
        while ((RecBytes = netstream.Read(RecData, 0, 1024)) > 0)
        {
        //I defined print in another context...
        totalrecbytes += RecBytes;
        if(RecBytes!=1024)
        print("Cycle : "+ nciclo +" Content RecBytes : " + RecBytes + " e RecData.Length : " + RecData.Length + " byte reads : " + totalrecbytes + ".");

        Fs.Write(RecData, 0, RecBytes);

        if (totalrecbytes >= size)
        {
            print("Read all bytes " + totalrecbytes + " over " + size + " .");
            break;
        }

        //Refresh the buffer
        RecData = new byte[1024];

        nciclo++;
        }

print("End of transfer. Received " + totalrecbytes + "File :" + filename + " Saved on " + tempFold);
Fs.Close();


}
catch (Exception ex)
{
//Ok here i return false, but i do some other stuff before
return false;
}

return true;
}

----服务器端结束--------------

--------客户端--------------

.....DOING STUFFS....
//sw is the streamWriter, Sr the streamReader and the stream is the networkstream

System.Collections.Specialized.StringCollection formats = Clipboard.GetFileDropList();
sw.WriteLine("CLIENT:FILE:" + formats.Count + "*");
sw.Flush();
   //Sending to the server filename and relative size
   foreach (string filename in formats)
    {
      //Ok the * has sense in my protocol...ignore it.
      sw.WriteLine((Directory.Exists(filename)) ? System.IO.Path.GetFileName(filename) + "*" : System.IO.Path.GetFileName(filename));
      sw.Flush();
      FileStream Fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
      sw.WriteLine(Fs.Length);
      sw.Flush();
      stream.Flush();
      Fs.Close();
     }
     //Sending files     
     foreach (string filename in formats)
     {    
    //client_sync is the class that wrap the TcpClient socket
        client_sync.send_single_file(stream, filename);
        resp = sr.ReadLine();                
     }
....DOING STUFF AND end of this function...

The send file function is defined in this way :
(note : i take this function from code project some weeks ago)
public void send_single_file(NetworkStream netstream, string filename)
        {
        //connected is a param of my class
            if (!connected) return;
            byte[] SendingBuffer = null;
            try
            {

                FileStream Fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
                int NoOfPackets = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(Fs.Length) / Convert.ToDouble(this.BufferSize)));
        //NOTE: BUFFERSIZE IS 1024
                int TotalLength = (int)Fs.Length, CurrentPacketLength = 0;
                int bytes_send = 0;

                for (int i = 0; i < NoOfPackets; i++)
                {
                    if (TotalLength > this.BufferSize)
                    {
                        CurrentPacketLength = this.BufferSize;
                        TotalLength = TotalLength - CurrentPacketLength;
                    }
                    else
                        CurrentPacketLength = TotalLength;

                    SendingBuffer = new byte[CurrentPacketLength];
                    Fs.Read(SendingBuffer, 0, CurrentPacketLength);
                    netstream.Write(SendingBuffer, 0, SendingBuffer.Length);
                    bytes_send += CurrentPacketLength;

                }
                Fs.Close();

            }
            catch (Exception ex)
            {
                netstream.Close();
                //my function
                close_connection();
            }
            netstream.Flush();

        }

---------客户端结束------

所以...有人可以帮助我摆脱这个地狱??? THX:)

0 个答案:

没有答案