NetworkStream.Write卡住了。写入超时后我该怎么办?

时间:2018-04-11 17:30:38

标签: c# tcp timeout tcpclient networkstream

我尝试将文件从TCPClient发送到具有1000字节缓冲区的TCPListener。 TCPClient位于一个应用程序"服务器"并且TCPListener位于另一个应用程序" client"中。在测试时,两者都在localhost上运行。 我的问题是NetworkStream.Write方法卡住了(参见截图和代码)。我不知道为什么。谷歌搜索后我怀疑套接字缓冲区已满。所以我将WriteTimeout设置为3000毫秒来处理问题。但我无法找到一个刷新方法,以防万一缓冲区出现问题。我该怎么办?

服务器代码(卡在NetworkStream.Write中的代码):

private void fetchThreadMethod(Object commandArgs)
    {
        byte[] buffer = new byte[1000];
        byte[] comMessage = new byte[35];
        IPEndPoint localEP = new IPEndPoint(localIP,1304);
        TcpClient client = new TcpClient(localEP);
        client.Connect(localIP,1305);
        Thread.Sleep(1000);
        Console.WriteLine("SERVER: Connected to client.");
        NetworkStream nStream = client.GetStream();
        client.NoDelay = true;
        client.Client.NoDelay = true;
        nStream.WriteTimeout = 3000;
        FileCollector fCollector = new FileCollector();
        String currUserVar = Environment.GetEnvironmentVariable("USERPROFILE");
        fCollector.startFileCollector(currUserVar + "\\" + commandArgs);
        List<FileNode> collectedFiles = fCollector.getCollectedFiles();
        ulong byteCount = 0;
        FileStream fStream = null;

        foreach (FileNode fNode in collectedFiles)
        {
            String filePath = fNode.getFileName();
            try
            {
                fStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            }
            catch (Exception e)
            {
                Console.WriteLine("SERVER: Exception when opening file " + filePath + " with a FileStream.");
                continue;
            }

            FileInfo fInfo = new FileInfo(fNode.getFileName());
            String fileHeaderStr = null;
            String fileName = fNode.getFileName().Split('\\').Last();
            ulong fileSize = (ulong) fInfo.Length;
            fileHeaderStr = "FHEAD" + fileName + "FNAME" + fileSize.ToString() + "FSIZE";
            byte[] fileHeaderStrBytes = Encoding.ASCII.GetBytes(fileHeaderStr);
            byte[] fileHeader = new byte[400];
            for(int i = 0; i < fileHeaderStrBytes.Length; i++)
                fileHeader[i] = fileHeaderStrBytes[i];

            ulong sentBytesCount = 0;
            String comStr = String.Empty;
            byte readByte = 0;
            int readByteInt = 0;
            while(sentBytesCount < fileSize)
            {
                Console.WriteLine("SERVER: Waiting for CLIENT_READY.");
                while (!comStr.Equals("CLIENT_READY"))
                {
                    nStream.Read(comMessage, 0, 35);
                    comStr = Encoding.ASCII.GetString(comMessage).Split(new String[] { "ENDC" }, StringSplitOptions.None)[0];
                }
                Console.WriteLine("SERVER: Received CLIENT_READY.");
                if (sentBytesCount == 0)
                {
                    for (int j = 0; j < 400; j++)
                        buffer[j] = fileHeader[j];
                    for(int k = 400; k < 1000; k++)
                    {
                        readByteInt = fStream.ReadByte();
                        if (readByteInt != -1)
                        {
                            readByte = Convert.ToByte(readByteInt);
                            buffer[k] = readByte;
                            sentBytesCount++;
                        }
                        else{
                            buffer[k] = 0;
                        }
                    }
                }
                else
                {
                    for(int l = 0; l < 1000; l++)
                    {
                        readByteInt = fStream.ReadByte();
                        if (readByteInt != -1)
                        {
                            readByte = Convert.ToByte(readByteInt);
                            buffer[l] = readByte;
                            sentBytesCount++;
                        }
                        else
                        {
                            buffer[l] = 0;
                        }
                    }
                }
                try
                {
                    Console.WriteLine("SERVER: Writing to network stream...");
                    // Gets stuck here! Timeout set to 3000 ms. Throws cought IOException.
                    nStream.Write(buffer, 0, 1000);
                    Console.WriteLine("SERVER: Wrote to network stream.");
                }catch(IOException ioe)
                {
                    Console.WriteLine("SERVER: Network stream write timed out.");
                    // ??? What should I do here? ???
                }
            }
            Console.WriteLine("SERVER: File sent:" + fileName);
        }
        Console.WriteLine("SERVER: All accessible files downloaded from " + (String) commandArgs);
    }

客户端代码,即接收等待卡住服务器的文件的代码:

private void fetchFilesThreadMethod()
    {
        IPEndPoint localEP = new IPEndPoint(localIP, 1305);
        TcpListener listener = new TcpListener(localEP);
        listener.Start();
        TcpClient client = listener.AcceptTcpClient();
        NetworkStream nStream = client.GetStream();
        byte[] buffer = new byte[1000];
        byte[] comMessage = new byte[35];
        byte[] comMessageBytes = Encoding.ASCII.GetBytes("CLIENT_READYENDC");
        for (int i = 0; i < comMessageBytes.Length; i++)
            comMessage[i] = comMessageBytes[i];

        ulong bytesRecCount = 0;
        ulong fileSize = 0;
        ulong bytesLeft = 0;
        String fileName = null;
        while (true)
        {
            nStream.Write(comMessage, 0, 35);
            Console.WriteLine("CLIENT: Sent CLIENT_READY.");
            nStream.Read(buffer, 0, 1000);
            byte[] headerBytes = new byte[400];
            for (int j = 0; j < 400; j++)
                headerBytes[j] = buffer[j];
            String headerStr = Encoding.ASCII.GetString(headerBytes);
            if (headerStr.Contains("FHEAD") || headerStr.Contains("FNAME") || headerStr.Contains("FSIZE"))
            {
                byte[] fileCont = new byte[600];
                for (int k = 400; k < 1000; k++)
                    fileCont[k-400] = buffer[k];
                fileName = headerStr.Split(new String[] { "FNAME" }, StringSplitOptions.None)[0];
                fileName = fileName.Split(new String[] { "FHEAD" }, StringSplitOptions.None).Last();
                String fileSizeStr = headerStr.Split(new String[] {"FSIZE"},StringSplitOptions.None)[0];
                fileSizeStr = fileSizeStr.Split(new String[] { "FNAME" }, StringSplitOptions.None).Last();
                fileSize = Convert.ToUInt64(fileSizeStr);
                String dirPath = Environment.GetEnvironmentVariable("USERPROFILE") + "\\documents\\conquer_client_fetches";
                if (!Directory.Exists(dirPath))
                    Directory.CreateDirectory(dirPath);
                String filePath = dirPath + "\\" + fileName;
                fStream = new FileStream(filePath,FileMode.Append,FileAccess.Write);

                if(fileSize < 600)
                {
                    fStream.Write(fileCont,0,(int) fileSize);
                    bytesRecCount = fileSize;
                    bytesLeft = fileSize - bytesRecCount;
                }
                else
                {
                    fStream.Write(fileCont, 0, 600);
                    bytesRecCount = 600;
                    bytesLeft = fileSize - bytesRecCount;
                }
            }
            else
            {
                if(bytesLeft < 1000)
                {
                    fStream.Write(buffer,0,(int) bytesLeft);
                    bytesRecCount += bytesLeft;
                    bytesLeft = fileSize - bytesRecCount;
                }else
                {
                    fStream.Write(buffer,0,1000);
                    bytesRecCount += 1000;
                    bytesLeft = fileSize - bytesRecCount;
                }
            }
        }
    }

enter image description here

enter image description here

我得到以下异常:

  System.IO.IOException: Unable to write data to the transport connection: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. ---> System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
   at System.Net.Sockets.Socket.Send(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
   at System.Net.Sockets.NetworkStream.Write(Byte[] buffer, Int32 offset, Int32 size)
   --- End of inner exception stack trace ---
   at System.Net.Sockets.NetworkStream.Write(Byte[] buffer, Int32 offset, Int32 size)
   at Conquer_server.Conquer_server.fetchThreadMethod(Object commandArgs) in C:\Users\tobb9\source\repos\Conquer_server\Conquer_server\Conquer_server.cs:line 241
-2146232800
Unable to write data to the transport connection: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.

0 个答案:

没有答案