0

WCFサービスを使用して、tcpソケットを介してファイルとフォルダーを送信する小さなファイル転送アプリケーションがあります。クライアントからの転送操作(backgroundworker)をキャンセルしても、サーバーがまだフリーズして
いるという私の問題は、この例外が発生したと思われますが、クライアント側ではリスナー側になりますが、そうではありません。 Connectedになる と、この例外を取得して処理する必要があります。これにより、ストリームとソケットを閉じて、別のタスクを受信できるようになります。client.ReceiveAn existing connection was forcibly closed by the remote hostfalsefalse

クライアント側:

private void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        List<Job> Jobs = (List<Job>)e.Argument;
        using (Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
        {
            IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 0);
            listener.Bind(endpoint);
            listener.Listen(1);
            client.ConnectToClient((IPEndPoint)listener.LocalEndPoint);
            Socket socket = listener.Accept();
            foreach (Job job in Jobs)
            {
                if (job.IsFile)
                   {
                      if (job.IsSend)
                      { SendFile(socket, job, e); }  //here i send a single file.
         //           else
         //           { ReceiveFile(socket, job, e); }
                   }
         //        else
         //        {
         //           if (job.IsSend)
         //           { SendDir(socket, job, e); }
         //           else
         //           { ReceiveDir(socket, job, e); }
         //        }
                if (worker.CancellationPending)
                {
                    e.Cancel = true;
                    socket.Dispose();
                    listener.Dispose();
                    Console.WriteLine(socket.Connected + "  " + listener.Connected);  
                    //it prints "FALSE FALSE"
                    return;
                }
            }
        }
    }

private void SendFile(Socket socket, Job job, DoWorkEventArgs e)
    {
        UpdateInfo(job.Name, job.Icon);              //update GUI with file icon and name.
        client.ReceiveFile((_File)job.Argument, bufferSize); //tell the client to start receiving
        SendX(socket, ((_File)job.Argument).Path, e);    //start sending..
    }

private void SendX(Socket socket, string filePath, DoWorkEventArgs e)
    {
        using (Stream stream = File.OpenRead(filePath))
        {
            byte[] buffer = new byte[bufferSize];
            long sum = 0;
            int count = 0;
            while (sum < stream.Length)
            {
                if (worker.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
                count = stream.Read(buffer, 0, buffer.Length);
                socket.Send(buffer, 0, count, SocketFlags.None);
                sum += count;
                SumAll += count;
                worker.ReportProgress((int)((sum * 100) / stream.Length));
            } 
        }
    }

サーバ側:

public void ConnectToClient(IPEndPoint endpoint)
    {
        if (client == null)
        {
            Thread th = new Thread(unused => ConnectTh(endpoint));
            th.Start();
        }
    }
    private void ConnectTh(IPEndPoint endpoint)
    {
        client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        client.Connect(IPAddress.Parse("127.0.0.1"), endpoint.Port);
    }


public void ReceiveFile(_File file, int bufferSize)
    {
        System.Threading.Thread th = new System.Threading.Thread(unused => ReceiveX(client, file.Name, file.Size, bufferSize));
        th.Start();
    }

private void ReceiveX(Socket client, string destPath, long size, int bufferSize)
    {
        try
        {
            using (Stream stream = File.Create(destPath))
            {
                byte[] buffer = new byte[bufferSize];
                long sum = 0;
                int count = 0;
                while (sum < size)
                {
                    int bytesToReceive = (int)Math.Min(buffer.Length, size - sum);
                    count = client.Receive(buffer, 0, bytesToReceive, SocketFlags.None);
                    stream.Write(buffer, 0, count);
                    sum += count;
                }
            }
        }
        catch
        {
            if (File.Exists(destPath))
                File.Delete(destPath);
            client.Dispose();
        }
    }
4

1 に答える 1

0

通常のプログラムフローの例外を決して期待してはいけません(しなければなりません)。

クライアント側がソケットをシャットダウンすると、サーバーは0バイトのパケットを受信し、を呼び出すたびにそれを受信し続けますReceive。これにより、whileループが永久に続きます。0の状況をcount処理し、通常の「クライアントによって閉じられた接続」として扱う必要があります。あなたが言及した例外は、クライアント側が適切にシャットダウンできなかった場合にのみ発生します。

于 2012-04-25T18:08:08.720 に答える