How to cancel TCP C # file transfer

I have a recipient and sender client that pretty much transfers files. This is what I still got on the receiver:

Thread t1; int flag = 0; string receivedPath; public delegate void MyDelegate(string s); int bytesRead = 0; bool endReceive = false; public Form1() { t1 = new Thread(new ThreadStart(StartListening)); t1.Start(); InitializeComponent(); } public class StateObject { // Client socket. public Socket workSocket = null; public const int BufferSize = 1024*100; // Receive buffer. public byte[] buffer = new byte[BufferSize]; } public static ManualResetEvent allDone = new ManualResetEvent(false); public void StartListening() { byte[] bytes = new Byte[1024*1000]; IPEndPoint ipEnd = new IPEndPoint(IPAddress.Any, 9050); 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(); if (endReceive) { listener.Disconnect(true); } } } 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; handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); flag = 0; } public void ReadCallback(IAsyncResult ar) { int fileNameLen = 1; String content = String.Empty; StateObject state = (StateObject)ar.AsyncState; Socket handler = state.workSocket; try { bytesRead= handler.EndReceive(ar); } catch (SocketException x) { MessageBox.Show("File Transfer was cancelled"); Invoke(new MyDelegate(LabelWriter), new object[] { "Waiting for connections" }); if (File.Exists(receivedPath)) { File.Delete(receivedPath); return; } } if (endReceive) { handler.Disconnect(true); if (File.Exists(receivedPath)) { File.Delete(receivedPath); } return; } if (bytesRead > 0) { if (flag == 0) { fileNameLen = BitConverter.ToInt32(state.buffer, 0); string fileName = Encoding.UTF8.GetString(state.buffer, 4, fileNameLen); receivedPath = fileName; Invoke(new MyDelegate(LabelWriter), new object[] { "Receiving File: " + fileName }); flag++; } if (flag >= 1) { BinaryWriter writer = new BinaryWriter(File.Open(receivedPath, FileMode.Append)); if (flag == 1) { writer.Write(state.buffer, 4 + fileNameLen, bytesRead - (4 + fileNameLen)); flag++; ReleaseMemory(); } else writer.Write(state.buffer, 0, bytesRead); writer.Close(); try { handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); } catch (SocketException exc) { MessageBox.Show("File Transfer was cancelled"); Invoke(new MyDelegate(LabelWriter), new object[] { "Waiting for connections" }); if (File.Exists(receivedPath)) { File.Delete(receivedPath); return; } } } } else Invoke(new MyDelegate(LabelWriter), new object[] {"Data Received"}); } 

What I want to achieve is the ability to cancel the transfer during its implementation. What I had in mind was to set the boolean value "EndReceive" to false, and each time the ReadCallBack method is called, EndReceive is checked. If it is a lie, I will disconnect the socket. It works by stopping the receipt of the file, however the sending application just freezes. This is basically how I post:

  while (true) { int index = 0; while (index < fs.Length) { int bytesRead = fs.Read(fileData, index, fileData.Length - index); if (bytesRead == 0) { break; } index += bytesRead; } if (index != 0) { try { clientSock.Send(fileData, index, SocketFlags.None); } catch (Exception sexc) { MessageBox.Show("Transfer Cancelled"); return; } ReleaseMemory(); if ((progressBar1.Value + (1024 * 1000)) > fs.Length) { progressBar1.Value += ((int)fs.Length - progressBar1.Value); } else progressBar1.Value += (1024 * 1000); lblSent.Text = index.ToString(); } if (index != fileData.Length) { ReleaseMemory(); progressBar1.Value = 0; clientSock.Close(); fs.Close(); break; } } 

Any thoughts?

+4
source share
1 answer

It seems to me that it is difficult to force an interrupt for the kind of mass transfers you make and completely close it with TCP. What if you take a block size of 1024 and after each transmission kB send a fast byte or a nack bit from the receiver to the sender? Nack indicating the transfer should be aborted, ack indicates the continuation.

Unfortunately, this requires full duplex transmission for the receiver / sender, and be careful! Although this is an asynchronous IO, you need to call BeginReceive and BeginSend on separate threads if you plan and read and write from the same socket.

+2
source

All Articles