Member 10844632 Ответов: 1

Отправка и получение нескольких файлов по протоколу TCP


Привет,

У меня есть tcp-отправитель, который отправляет большой файл по протоколу tcp.
У меня есть приемник, который принимает файлы и сохраняет их на диск.
Он отлично работает для одного файла, для нескольких файлов это не работает!
Я гуглил несколько дней, прошелся почти по всем статьям и не нашел решения.
Я был бы очень признателен, если бы кто-то мог помочь мне и заставить мой код работать так, как мне нужно!!!
заранее спасибо!


В отправителе у меня есть fileSystemWatcher, который следит за папкой, и когда файл создается, он берет файл и отправляет его по tcp, отправителем.

Вот код отправителя:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Sender
{
    /// <summary>
    /// SocketSender is used to asynchronously listen the client and send file to the client.
    /// </summary>
    public   class SocketSender
    { 
        
        #region Memebers
    
        private  IPEndPoint targetEndPoint = null;
        private bool _isConnected;
        Socket clientSock = null;
        private ManualResetEvent PauseIfDisconnected;

        #endregion


        public SocketSender(IPEndPoint ipEndPoint)
        {
            targetEndPoint= ipEndPoint;
            clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _isConnected = false;
            PauseIfDisconnected = new ManualResetEvent(_isConnected);
        }


        public void Connect()
        {
            try
            {
                while (true)
                {
                    if (!_isConnected)
                    {
                        try
                        {
                            // Connect
                            clientSock = null;
                           clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                            clientSock.Connect(targetEndPoint); //target machine's ip address and the port number

                            PauseIfDisconnected.Set();
                            _isConnected = true;
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("======= ERROR Connect function =====");
                            Console.WriteLine(ex.ToString());
                        }
                    }
                    else
                    {
                        if (!clientSock.Connected)
                        {
                            PauseIfDisconnected.Reset();
                            _isConnected = false;
                            clientSock.Close();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("======= ERROR Connect function =====");
                Console.WriteLine(ex.ToString());
            }
        }
       
 

        /// <summary>
        /// Send file information to client
        /// </summary>
        public void Send(string fileToSend)
        {
            if (targetEndPoint == null)
                return;

            Socket clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);


            // Turn xml to bytes array
            byte[] fileName = Encoding.UTF8.GetBytes(Path.GetFileName(fileToSend)); //file name

           //This line - read bytes cause after the first time- an exception of :the file is being used by another process. but if I debug it- it works and doesn't fail (why?)
            byte[] fileData = File.ReadAllBytes(fileToSend); //file


            byte[] fileNameLen = BitConverter.GetBytes(fileName.Length); //lenght of file name
          var  clientData = new byte[4 + fileName.Length + fileData.Length];

            fileNameLen.CopyTo(clientData, 0);
            fileName.CopyTo(clientData, 4);
            fileData.CopyTo(clientData, 4 + fileName.Length);


            try
            {
                clientSock.Connect(targetEndPoint);
                clientSock.Send(clientData);
                clientSock.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine("======= ERROR Send function =====");
                Console.WriteLine(ex.ToString());

           
            }
           
        }
    }
}


Это код приема (другой проект):

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Receiver
{

    /// <summary>
    /// AsynchronousClient is used to asynchronously receive the file from server.
    /// </summary>
    public   class AsynchronousClient
    {

        #region Members

          Thread t1;
          int flag = 0;
         IPEndPoint ipEnd = null;
         string folderSavePath;
         public static ManualResetEvent allDone = new ManualResetEvent(false);

        #endregion

         public AsynchronousClient(IPEndPoint ipEndPoint, string fSavePath)
         {
             ipEnd = ipEndPoint;
             folderSavePath = fSavePath;

             t1 = new Thread(new ThreadStart(StartListening));
             t1.Start();
         }


        /// <summary>
        /// Start connect to the server.
        /// </summary>
        public   void StartListening()
        {
            if (ipEnd == null)
                return;

  
            Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                listener.Bind(ipEnd);
                listener.Listen(100);
                while (true)
                {
                    allDone.Reset();
                    listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
                    allDone.WaitOne();

                }
            }
            catch (Exception ex)
            {

            }

        }

        public   void AcceptCallback(IAsyncResult ar)
        {

            allDone.Set();


            Socket listener = (Socket)ar.AsyncState;
            Socket handler = listener.EndAccept(ar);


            StateObject state = new StateObject();
            state.WorkSocket = handler;

            // Begin to receive the file from the server.
            handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
            flag = 0;
        }

        string fileSavePath = string.Empty;

        /// <summary>
        /// Receive the file send by the server.
        /// </summary>
        public   void ReadCallback(IAsyncResult ar)
        {
           
            int fileNameLen = 1;
            String content = String.Empty;
            StateObject state = (StateObject)ar.AsyncState;
            Socket handler = state.WorkSocket;
            int bytesRead = handler.EndReceive(ar);
           

            try
            {
                if (bytesRead > 0)
                {

                    if (flag == 0)
                    {

                        //create the folder for saving if needed

                        if (!Directory.Exists(folderSavePath))
                        {
                            Directory.CreateDirectory(folderSavePath);
                        }

                        // Get the filename length from the server.
                        fileNameLen = BitConverter.ToInt32(state.Buffer, 0);
                        string fileName = Encoding.UTF8.GetString(state.Buffer, 4, fileNameLen);

                        fileSavePath = folderSavePath + "\\" + fileName;
                        flag++;
                    }
                    if (flag >= 1)
                    {
                        using (BinaryWriter writer = new BinaryWriter(File.Open(fileSavePath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite)))
                        {
                            if (flag == 1)
                            {
                                writer.Write(state.Buffer, 4 + fileNameLen, bytesRead - (4 + fileNameLen));
                                flag++;
                            }
                            else
                                writer.Write(state.Buffer, 0, bytesRead);

                            writer.Flush();
                            writer.Close();
                        }

                            handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0,
                            new AsyncCallback(ReadCallback), state);
                        
                    }

                }
                else
                {
                    handler.Close();
                }
            }
            catch(Exception ex)
            {

            }

        }

      
    }

    }


Что я уже пробовал:

Я попытался разработать отправитель tcp, который отправляет несколько больших файлов по протоколу TCP,
и приемник, который слушает и получает файлы из TCP и сохраняет их на диск.

Mehdi Gholam

Попробуйте отправить блоки.

Richard MacCutchan

Вы не объяснили, что происходит, когда вы пытаетесь отправить более одного файла.

Member 10844632

Что-то в приемнике не работает так, как нужно. Он просто выбрасывает из диапазона excption, кажется, что он продолжает файлы вместе, а не один за другим или все в PERELAL

Richard MacCutchan

Что-то в приемнике не работает так, как нужно
Затем вам нужно использовать свой отладчик, чтобы узнать, что это такое; мы не можем догадаться, и мы не можем видеть ваш экран, чтобы знать, что происходит.

Member 10844632

Я имел в виду "что - то" - то, что я не знаю, что изменить, чтобы запустить его по мере необходимости с несколькими файлами.
Приемник выбрасывает исключение из диапазона при повторном вызове, когда я отправляю несколько файлов один за другим

Richard MacCutchan

И почему вы думаете, что мы будем знать, что изменить, с такой неопределенной информацией? Как я уже говорил, вам нужно выполнить некоторую отладку, чтобы выяснить, где возникает ошибка и какие значения находятся вне диапазона и почему.

Rob Philpott

Дикая догадка, небрежно глядя на код. Я бы сказал, что использование Waithandles является необычным и ненужным, и в приемнике сигнал приходит до EndAccept, заставляя его потенциально повторно войти в тот же экземпляр. Попробуйте переместить набор ниже EndAccept. Еще лучше, избавьтесь от дескриптора ожидания и выполните следующий BeginAccept сразу после EndAccept.

Member 13714031

Мне нужен полный код обмена файлами с сервера на несколько подключенных клиентов только для одного файла.

1 Ответов

Рейтинг:
2

Member 12599256

Просто взгляните на свой код вкратце:

the file is being used by another process

Это означает, что ваш файл читается, и вы хотите прочитать его снова в то же время.

Прочтите один раз, разбейте его на множество блоков и отправьте этот блок.