Отправка и получение нескольких файлов по протоколу 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
Мне нужен полный код обмена файлами с сервера на несколько подключенных клиентов только для одного файла.