C# socket sending large file over than 2 GB - c#

I am trying to send the large file(greater than 2 GB) via Sockets in C#. I am sending it in chunks of 10 MB.
I will explain what is my approach. From client side, I will send the chunk and will wait for confirmation from server(if that chunk has been received or not). After receving confirmation, I will send another chunk and will again wait for confimation from server for that chunk. The loop will continue till all file data has been sent to. After successful sent operation of file, will close the connection from client side.
Client Side Code:
try
{
DateTime startdate = DateTime.Now;
string ori_text = btn_Send_Files.Text;
btn_Send_Files.Text = "Do not click already sending...";
btn_Send_Files.Refresh();
IPAddress[] ipAddress = Dns.GetHostAddresses("localhost");
IPEndPoint ipEnd = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5656);
Socket clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
clientSock.Connect(ipEnd);
label1.Text = label1.Text + "\nConnected to:" + ipEnd.Address.ToString();
label1.Refresh();
string fileName = "CCCCCC.zip"; //It has size greater than 2 GB
string filePath = #"C:\Users\CCCCCC\Downloads\";
byte[] fileNameByte = Encoding.ASCII.GetBytes(fileName);
label1.Text = label1.Text + "\nSending the file:" + fileName;
label1.Refresh();
FileInfo fi = new FileInfo(filePath + fileName);
int max = 1024 * 1024 * 10;
long start = 0, bytesRead = 0;
FileStream fileStream = new FileStream(filePath + fileName, FileMode.Open, FileAccess.Read);
max = max - (4 + fileNameByte.Length);
byte[] tmpserver = new byte[100];
using (fileStream)
{
int i = 0;
while (start < fi.Length)
{
i += 1;
label1.Text = label1.Text + "\nSending " + i.ToString() + " block of file:" + fileName;
label1.Refresh();
fileStream.Seek(start, SeekOrigin.Begin);
if (max > (fi.Length - start))
max = Convert.ToInt32(fi.Length - start);
byte[] buffer = new byte[max];
byte[] clientData = new byte[4 + fileNameByte.Length + max];
byte[] fileNameLen = BitConverter.GetBytes(fileNameByte.Length);
fileNameLen.CopyTo(clientData, 0);
fileNameByte.CopyTo(clientData, 4);
bytesRead = fileStream.Read(buffer, 0, max);
start += max;
buffer.CopyTo(clientData, 4 + fileNameByte.Length);
clientSock.Send(clientData);
Array.Clear(clientData, 0, clientData.Length);
Array.Clear(buffer, 0, buffer.Length);
Array.Clear(fileNameLen, 0, fileNameLen.Length);
Array.Clear(clientData, 0, clientData.Length);
clientData = null;
buffer = null;
fileNameLen = null;
GC.Collect();
label1.Text = label1.Text + "\nWaiting for confirmation of " + i.ToString() + " block of file:" + fileName;
int serverdata = clientSock.Receive(tmpserver);
if (serverdata == 0)
{
clientSock.Shutdown(SocketShutdown.Both);
clientSock.Close();
break;
}
else
{
label1.Text = label1.Text + "\nReceived confirmation for " + i.ToString() + " block of file:" + fileName;
label1.Refresh();
}
}
}
clientSock.Close();
DateTime enddate = DateTime.Now;
TimeSpan diff = startdate - enddate;
label1.Text = label1.Text + "\nFile "+ fileName + " has been sent to:"+ ipEnd.Address.ToString();
label1.Text = label1.Text + "\nTime Taken to sent the file(seconds):" + Math.Abs(diff.Seconds).ToString();
label1.Refresh();
btn_Send_Files.Text = ori_text;
btn_Send_Files.Refresh();
}
catch (Exception ex)
{
MessageBox.Show("File Sending fail." + ex.ToString());
}
Server Side Code:
try
{
label1.Text = label_text;
label1.Refresh();
string ori_btn_text = btn_Start_Server.Text;
btn_Start_Server.Text = "Do not click already waiting...";
btn_Start_Server.Refresh();
label1.Text = label1.Text + "\nWaiting for client";
label1.Refresh();
string receivedPath = ConfigurationManager.AppSettings["Location"];
Socket clientSock = sock.Accept();
label1.Text = label1.Text + "\nServer Started and connected to client" + clientSock.LocalEndPoint + "\nWaiting for the file to receive";
label1.Refresh();
int max = 1024*1024*10;
string logfile = receivedPath + "\\serverlog.log";
if (File.Exists(logfile))
{
File.Delete(logfile);
}
FileStream fs = File.Create(logfile);
byte[] serverdata = new byte[100];
string fileName = "";
int fileNameLen = 0, fileDataLen = 0;
int i = 0;
BinaryWriter bWrite = null;
while (true)
{
i += 1;
byte[] clientData = new byte[max];
int receivedBytesLen = clientSock.Receive(clientData);
if (receivedBytesLen <= 0)
break;
string tmp = "\nStarted:" + i;
fs.Write(Encoding.ASCII.GetBytes(tmp), 0, Encoding.ASCII.GetBytes(tmp).Length);
if (i == 1)
{
fileNameLen = BitConverter.ToInt32(clientData, 0);
fileName = Encoding.ASCII.GetString(clientData, 4, fileNameLen);
fileDataLen = BitConverter.ToInt32(clientData, 4);
if (File.Exists(receivedPath + fileName))
{
File.Delete(receivedPath + fileName);
}
bWrite = new BinaryWriter(File.Open(receivedPath + fileName, FileMode.Create));
label1.Text = label1.Text + "\nReceiving File:" + fileName;
}
label1.Text = label1.Text + "\nReceived " + i.ToString() + " block of file:" + fileName;
label1.Refresh();
bWrite.Write(clientData, 4 + fileNameLen, receivedBytesLen - 4 - fileNameLen);
Array.Clear(clientData, 0, clientData.Length);
clientData = null;
GC.Collect();
clientSock.Send(serverdata);
label1.Text = label1.Text + "\nSent confirmation for " + i.ToString() + " block of file:" + fileName;
label1.Refresh();
}
if (bWrite != null)
{
bWrite.Flush();
bWrite.Dispose();
bWrite.Close();
}
fs.Close();
label1.Text = label1.Text + "\nFile has been received:" + fileName;
label1.Refresh();
MessageBox.Show("File has been received:" + fileName);
btn_Start_Server.Text = ori_btn_text;
btn_Start_Server.Refresh();
}
catch (Exception ex)
{
MessageBox.Show("File Receiving fail." + ex.ToString());
}
It works fine on locally but over the network getting timeout exception on .receive() method on server side.

I strongly suggest you don't try to reinvent the wheel. There is no need to mess around with sockets and chunks of files.
Instead just open the file as a FileStream and copy it straight into a NetworkStream, which you can get using TcpClient (and TcpListener for the server).
You should also convert this code to be fully async.
public async void btn_Send_Files_Click(object sender, EventArgs e)
{
DateTime startdate = DateTime.Now;
try
{
string ori_text = btn_Send_Files.Text;
btn_Send_Files.Text = "Do not click already sending...";
btn_Send_Files.Enabled = false;
await SendFileAsync();
label1.Text += $"\nFile {fileName} has been sent to: {ipEnd.Address}\nTime Taken to sent the file(seconds):{Math.Abs(diff.Seconds)}";
}
catch (Exception ex)
{
MessageBox.Show("File Sending fail." + ex.ToString());
}
finally
{
DateTime enddate = DateTime.Now;
TimeSpan diff = startdate - enddate;
btn_Send_Files.Text = ori_text;
btn_Send_Files.Enabled = true;
}
}
private async Task SendFiles()
{
string fileName = "CCCCCC.zip"; //It has size greater than 2 GB
string filePath = #"C:\Users\CCCCCC\Downloads\";
using (var fileStream = new FileStream(Path.Combine(filePath, fileName), FileMode.Open, FileAccess.Read))
using (var client = new TcpClient())
{
await client.ConnectAsync(IPAddress.Any, 5656); // replace with remote IP
label1.Text += $"\nConnected to:{client.Client.RemoteEndPoint}";
label1.Refresh();
using (var netStream = client.GetStream())
{
await fileStream.CopyToAsync(netStream);
}
}
}
Server-side code
public async void btn_Start_Server_Click(object sender, EventArgs e)
{
try
{
label1.Text = label_text;
string ori_btn_text = btn_Start_Server.Text;
btn_Start_Server.Text = "Do not click already waiting...";
btn_Start_Server.Enabled = false;
label1.Text = label1.Text + "\nWaiting for client";
label1.Refresh();
await WaitForFile("SomeFilename");
label1.Text = label1.Text + "\nFile has been received:" + fileName;
MessageBox.Show("File has been received:" + fileName);
}
catch (Exception ex)
{
MessageBox.Show("File Receiving fail." + ex.ToString());
}
finally
{
btn_Start_Server.Text = ori_btn_text;
btn_Start_Server.Enabled = true;
}
}
private Task WaitForFile(string fileName)
{
string receivedPath = ConfigurationManager.AppSettings["Location"];
var listener = new TcpListener(IPAddress.Any, 5656); // local IP to listen at, do not change
try
{
listener.Start();
using (var client = await listener.AcceptTcpClientAsync())
using (var networkStream = client.GetStream())
using (var fileStream = new FileStream(Path.Combine(receivedPath, fileName), FileMode.Create, FileAccess.Write))
{
label1.Text = $"{label1.Text}\nServer Started and connected to client {client.Client.RemoteEndPoint}\nWaiting for the file to receive";
label1.Refresh();
await networkStream.CopyToAsync(fileStream);
}
}
finally
{
if (listener.Active)
listener.Stop();
}
}
Your existing code also passes the filename through the stream. I'm sure you will manage to adapt the above to do the same.
Also, if you want to show progress, it could get more complicated. You may need to write your own FileStream-derived class.

Related

FTP Server generates "Error: 150 Opening data channel for file download"

I have write code for transfer file from FTP server to local server and after transfer 2 or 3 files it throwing exception error The remote server returned an error: 150 Opening data channel for file download
All File transfered successfully in FileZila but error coming in asp.net application.
I do the following code
protected string TransferFile(string strPath, string strFtpPath, string strFtpUser, string strFtpPwd, string strSubClientFTPPath, string strSubClientFTPUser, string strSubClientFTPPwd, string strFileName, string strConvFileName, string strFileSize)
{
string strSuccess = "";
FtpWebRequest reqFTP;
try
{
Double Size = 0;
string strLocalFileSize = "";
if (File.Exists(strPath + strConvFileName))
{
Size = ((Math.Round(Convert.ToDouble(new FileInfo(strPath + strConvFileName).Length)) > 0 && Math.Round(Convert.ToDouble(new FileInfo(strPath + strConvFileName).Length)) < 1024) ? 1 : (Math.Round(Convert.ToDouble(new FileInfo(strPath + strConvFileName).Length) / 1024 + 0.0001)));
strLocalFileSize = Size + "KB";
}
if (!File.Exists(strPath + strConvFileName) || strFileSize != strLocalFileSize)
{
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(strFtpPath + strFileName.Replace("#", "%23")));
System.Net.ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
reqFTP.EnableSsl = true;
reqFTP.Timeout = Timeout.Infinite;
reqFTP.KeepAlive = true;
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
//reqFTP.UseBinary = true;
//reqFTP.UsePassive = false;
reqFTP.Credentials = new NetworkCredential(strFtpUser, strFtpPwd);
// lblTransferredFile.Text = "Transferring " + strFileName + " ......";
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream ftpStream = response.GetResponseStream();
long cl = response.ContentLength;
int bufferSize = 2048;
int readCount;
byte[] buffer = new byte[bufferSize];
// lblTransferredFile.Text = "Transferring " + strFileName + " ......";
readCount = ftpStream.Read(buffer, 0, bufferSize);
//if (readCount > 0)
//{
FileStream outputStream = new FileStream(strPath +
strConvFileName, FileMode.Create);
while (readCount > 0)
{
outputStream.Write(buffer, 0, readCount);
readCount = ftpStream.Read(buffer, 0, bufferSize);
}
ftpStream.Close();
outputStream.Close();
response.Close();
strSuccess = "";
}
else
{
strSuccess = "File Exists";
}
}
catch (Exception ex)
{
strSuccess = ex.Message;
ClientScript.RegisterStartupScript(this.GetType(), "strScript", "<script>alert('" + ex.Message.Trim().Replace("'", "") + "');</script>");
}
return strSuccess;
}
I've encountered this today after installing kb 4519976. Uninstalling this KB solved the problem. Could you check if this is also the solution in your case.
Context was an ftps tls 1.2 ECHDE connection which fails at the stage where the extra connection is started.

"The operation has timed out in ftp" this error occurs when downloading a zip file with slow network from the server

I am using ftp for downloading a zip file(size 10 MB to 70 MB) from server it was perfectly downloading but, when the network is slow, the error the operation has timed out in ftp is showing and then it comes to catch(Exception ex) in that the download() is called once again so it is redownloading again and again.
This project is created in .NET framework 4.0
I have increased the time of ftpWebRequest.Timeout = 6000; but still it doesn't work
public void Download(string localDirectory,string localFilename,string remoteDirectory,string remoteFileName)
{
string client_path=Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(localDirectory)));
string appPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
string configFile = System.IO.Path.Combine(appPath, "PACS.exe.config");
ExeConfigurationFileMap configFileMap = new ExeConfigurationFileMap();
configFileMap.ExeConfigFilename = configFile;
System.Configuration.Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);
config.AppSettings.Settings["client_path"].Value = client_path;
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
string str = Path.Combine(localDirectory, localFilename);
FileInfo fileInfo = new FileInfo(str);
FileStream fileStream = (FileStream)null;
WebException webException;
try
{
string path = Path.GetDirectoryName(Path.GetDirectoryName(remoteDirectory));
string path1 = Path.GetDirectoryName(Path.GetDirectoryName(localDirectory));
WebRequest sizeRequest = WebRequest.Create("ftp://" + "IP" + ":" + "port" + "/" + "C:\\KINSOLUTIONS\\Team\\Images\\1" + ".zip");
sizeRequest.Credentials = (ICredentials)new NetworkCredential("UserName", "Password");
sizeRequest.Method = WebRequestMethods.Ftp.GetFileSize;
int size = (int)sizeRequest.GetResponse().ContentLength;
FtpWebRequest ftpWebRequest = WebRequest.Create(new Uri("ftp://" + "IP" + ":" + "port" + "/" + "C:\\KINSOLUTIONS\\Team\\Images\\1" + ".zip")) as FtpWebRequest;
ftpWebRequest.Credentials = (ICredentials)new NetworkCredential("UserName", "Password");
ftpWebRequest.UsePassive = true;
ftpWebRequest.Timeout = 6000;
ftpWebRequest.KeepAlive = false;
ftpWebRequest.Method = "RETR";
ftpWebRequest.UseBinary = true;
fileStream = new FileStream(path1 + ".zip", FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
using(Stream responseStream = (ftpWebRequest.GetResponse() as FtpWebResponse).GetResponseStream())
{
byte[] buffer = new byte[32768];
int count = responseStream.Read(buffer, 0, 32768);
long num = (long)count;
int post = 0;
while (size != post || count != 0 )
{
bool result = System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();
while (!result)
{
result = System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();
if (result)
{
fileStream.Close();
Download(localDirectory, localFilename, remoteDirectory, remoteFileName);
}
}
fileStream.Write(buffer, 0, count);
count = responseStream.Read(buffer, 0, 32768);
int position = (int)fileStream.Position;
num += (long)count;
post = position;
}
fileStream.Close();
}
}
catch (WebException ex)
{
if (fileStream != null)
fileStream.Close();
this.Download(localDirectory, localFilename, remoteDirectory, remoteFileName);
}
finally
{
if (fileStream != null)
fileStream.Close();
}
}
Is there any other option for downloading the zip file in slow network?

sending big file with socket to server c#

I'm trying to send a file about 250 kb to server but i have a corruption and it seemd that tottaly transfered some bytes only. The flow of command is
Write to stream: Send\r\n
Write to stream: FileName\r\n
Write to stream: FileData \r\n
Close the connection
Here is the code:
TcpClient sendClient = new TcpClient(serverName, port);
SslStream sendStream = new SslStream(sendClient.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
try
{
sendStream.AuthenticateAsClient(serverName, null, SslProtocols.Ssl2, true);
sendStream.Write(Encoding.UTF8.GetBytes("Login\r\n" + username + "\r\n" + password + "\r\n"));
sendStream.Flush();
int bytesResp = -1;
byte[] buffer = new byte[1026];
bytesResp = sendStream.Read(buffer, 0, buffer.Length);
string response = Encoding.UTF8.GetString(buffer, 0, bytesResp);
if (response.Trim() == "OK")
{
byte[] fileNameByte = Encoding.UTF8.GetBytes(fileName + "\r\n");
byte[] fileData = File.ReadAllBytes(filePath);
byte[] newLine = Encoding.ASCII.GetBytes("\r\n");
byte[] clientData = new byte[4 + Encoding.ASCII.GetBytes("Send\r\n").Length + fileNameByte.Length + fileData.Length+newLine.Length];
byte[] fileNameLen = BitConverter.GetBytes(fileNameByte.Length);
byte[] send = Encoding.ASCII.GetBytes("Send\r\n");
send.CopyTo(clientData, 0);
fileNameLen.CopyTo(clientData, 4 + send.Length);
fileNameByte.CopyTo(clientData, send.Length);
fileData.CopyTo(clientData, 4 + fileNameByte.Length + send.Length);
newLine.CopyTo(clientData, 4+ fileNameByte.Length + send.Length + fileData.Length);
MessageBox.Show(clientData.Length.ToString());
sendStream.Write(clientData, 0, clientData.Length);
sendStream.Flush();
sendStream.Write(Encoding.UTF8.GetBytes("Quit\r\n"));
sendClient.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
Does anybody have an idea please?
You haven't told us about the other end of the connection, so this answer is partially speculative...
BitConverter.GetBytes(fileNameByte.Length); is likely to be a little-endian conversion.
Almost all network encoding will be big-endian, so this is a strong candidate for the failure.
I suggest you use the EndianBitConverter.Big converter from Jon Skeet's miscutil to get the proper encoding order.
I send file up to 1GB with this code
Server Code
using System;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.IO;
namespace Server_FileSend
{
public partial class Form1 : Form
{
Socket Server = null;
Socket Client = null;
Thread trStart;
Thread trRecive;
const int sizeByte = 1024;
public Form1()
{
InitializeComponent();
}
private void ReciveFile()
{
while (true)
{
try
{
byte[] b = new byte[sizeByte];
int rec = 1;
int vp = 0;
rec = Client.Receive(b);
int index;
for (index = 0; index < b.Length; index++)
if (b[index] == 63)
break;
string[] fInfo = Encoding.UTF8.GetString(b.Take(index).ToArray()).Split(':');
this.Invoke((MethodInvoker)delegate
{
progressBar1.Maximum = int.Parse(fInfo[0]);
});
string path = Application.StartupPath + "\\Downloads\\";
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
FileStream fs = new FileStream(path + fInfo[1], FileMode.Append, FileAccess.Write);
string strEnd;
while (true)
{
rec = Client.Receive(b);
vp = vp + rec;
strEnd = ((char)b[0]).ToString() + ((char)b[1]).ToString() + ((char)b[2]).ToString() + ((char)b[3]).ToString() + ((char)b[4]).ToString() + ((char)b[5]).ToString();
if (strEnd == "!endf!")
{
fs.Flush();
fs.Close();
MessageBox.Show("Receive File " + ((float)(float.Parse(fInfo[0]) / 1024)).ToString() + " KB");
break;
}
fs.Write(b, 0, rec);
this.Invoke((MethodInvoker)delegate
{
progressBar1.Value = vp;
});
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
Form1_FormClosing(null, null);
}
}
}
private void StartSocket()
{
Server.Listen(1);
Client = Server.Accept();
trRecive = new Thread(new ThreadStart(ReciveFile));
trRecive.Start();
}
private void Form1_Load(object sender, EventArgs e)
{
Server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
IPEndPoint IP = new IPEndPoint(IPAddress.Any, 5050);
Server.Bind(IP);
trStart = new Thread(new ThreadStart(StartSocket));
trStart.Start();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
try
{
trRecive.Abort();
trStart.Abort();
Environment.Exit(Environment.ExitCode);
}
catch (Exception)
{
Environment.Exit(Environment.ExitCode);
}
}
}
}
Client Code
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace Clienf_fileSend
{
public partial class Form1 : Form
{
Socket Client = null;
Thread trRecive;
const int sizeByte = 1024;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
IPEndPoint IP = new IPEndPoint(IPAddress.Parse(textBox1.Text), 5050);
Client.Connect(IP);
button1.Enabled = false;
button2.Enabled = true;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void SendFile(object FName)
{
try
{
FileInfo inf = new FileInfo((string)FName);
progressBar1.Invoke((MethodInvoker)delegate
{
progressBar1.Maximum = (int)inf.Length;
progressBar1.Value = 0;
});
FileStream f = new FileStream((string)FName, FileMode.Open);
byte[] fsize = Encoding.UTF8.GetBytes(inf.Length.ToString() + ":");
byte[] fname = Encoding.UTF8.GetBytes(inf.Name + "?");
byte[] fInfo = new byte[sizeByte];
fsize.CopyTo(fInfo, 0);
fname.CopyTo(fInfo, fsize.Length);
Client.Send(fInfo);
if (sizeByte> f.Length)
{
byte[] b = new byte[f.Length];
f.Seek(0, SeekOrigin.Begin);
f.Read(b, 0, (int)f.Length);
Client.Send(b);
}
else
{
for (int i = 0; i < (f.Length - sizeByte); i = i + sizeByte)
{
byte[] b = new byte[sizeByte];
f.Seek(i, SeekOrigin.Begin);
f.Read(b, 0, b.Length);
Client.Send(b);
progressBar1.Invoke((MethodInvoker)delegate
{
progressBar1.Value = i;
});
if (i + sizeByte >= f.Length - sizeByte)
{
progressBar1.Invoke((MethodInvoker)delegate
{
progressBar1.Value = (int)f.Length;
});
int ind = (int)f.Length - (i + sizeByte);
byte[] ed = new byte[ind];
f.Seek(i + sizeByte, SeekOrigin.Begin);
f.Read(ed, 0, ed.Length);
Client.Send(ed);
}
}
}
f.Close();
Thread.Sleep(1000);
Client.Send(Encoding.UTF8.GetBytes("!endf!"));
Thread.Sleep(1000);
MessageBox.Show("Send File " + ((float)inf.Length / 1024).ToString() + " KB");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void button2_Click(object sender, EventArgs e)
{
OpenFileDialog fdl = new OpenFileDialog();
if (fdl.ShowDialog() == DialogResult.OK)
{
trRecive = new Thread(new ParameterizedThreadStart(SendFile));
trRecive.Start(fdl.FileName);
}
fdl = null;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
try
{
trRecive.Abort();
Environment.Exit(Environment.ExitCode);
}
catch (Exception)
{
Environment.Exit(Environment.ExitCode);
}
}
}
}

Reading Data from Network Stream in TCP Listener

I'm having a network stream which is having filename and filedata in it. I'm sending files in some chunks and each chunk carries the filename for easy identification. Can you please help me in reading the network stream properly and writing all of the data to the file stream.
I seem to miss few bytes when i write the data from network stream.
Say for example filename length will be in oth index and filename will start from 4th index.
Client:
int NoOfPackets = Convert.ToInt32
(Math.Ceiling((Convert.ToDouble(Fs.Length))/ Convert.ToDouble(BufferSize)));
int TotalLength = (NoOfPackets *4+fileNameByte.Length) +(int)Fs.Length, CurrentPacketLength, counter = 0;
netstream1 = client.GetStream();
for (int i = 0; i < NoOfPackets+1 ; i++)
{
if (TotalLength > BufferSize)
{
CurrentPacketLength = BufferSize;
TotalLength = TotalLength - CurrentPacketLength;
}
else
CurrentPacketLength = TotalLength;
SendingBuffer = new byte[CurrentPacketLength];
fileNameLength.CopyTo(SendingBuffer, 0);
fileNameByte.CopyTo(SendingBuffer, 4);
Fs.Read(SendingBuffer, 4 + fileNameByte.Length, CurrentPacketLength - (4 + fileNameByte.Length));
netstream1.Write(SendingBuffer, 0, SendingBuffer.Length);
netstream1.Flush();
}
Listener Code:
client = Listener.AcceptTcpClient();
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
//client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, true);
client.Client.LingerState = new LingerOption(true, 300);
client.Client.SendTimeout = 300000;
client.Client.ReceiveTimeout = 300000;
client.NoDelay = true;
NetworkStream netstream = client.GetStream();
MemoryStream ms = new MemoryStream();
bool first = true;
string fullPath = "";
byte[] RecData = new byte[512000];
while ((RecBytes = netstream.Read
(RecData, 0, RecData.Length)) > 0)
{
int fileNameLen = RecData[0];
if (fileNameLen > 0 && first)
{
string name1 = "", name2 = "";
first = false;
name1 = Encoding.UTF8.GetString(RecData, 4, fileNameLen);
name2 = name1;
string folderName = "";
if (name2.Contains("\\"))
{
folderName = name2.Substring(0, name2.LastIndexOf("\\"));
if (!Directory.Exists("D:\\123\\" + folderName))
Directory.CreateDirectory("D:\\123\\" + folderName);
}
if (folderName != "")
fullPath = "D:\\123\\" + folderName + "\\" + name2.Substring(name2.LastIndexOf("\\") + 1);
else
fullPath = "D:\\123\\" + name2.Substring(name2.LastIndexOf("\\") + 1);
}
if (!File.Exists(fullPath))
{
//file = new FileStream(fullPath, FileMode.OpenOrCreate, FileAccess.Write);
while (true)
{
try
{
using (FileStream file = new FileStream(fullPath, FileMode.OpenOrCreate, FileAccess.Write))
{
if (RecBytes - (4 + fileNameLen) > 0)
file.Write(RecData, 4 + fileNameLen, RecBytes - (4 + fileNameLen));
break;
}
}
catch (IOException)
{
Thread.Sleep(20);
}
}
//using (file = File.Create(fullPath))
//{
// file.Write(data, 4 + fileNameLen, (int)data.Length - (4 + fileNameLen));
//}
}
else
{
while (true)
{
try
{
using (FileStream file = new FileStream(fullPath, FileMode.Append, FileAccess.Write))
{
if (RecBytes - (4 + fileNameLen) > 0)
file.Write(RecData, 4 + fileNameLen, RecBytes - (4 + fileNameLen));
break;
}
}
catch (IOException)
{
Thread.Sleep(20);
}
}
}
}
ms.Close();
netstream.Close();
client.Close();
even though you are as vague as anyone can be, still I would suggest that you create a structure so that serialization and de-serialization of data could be done in a known format!! and data loss could be avoided!!
Again if your approach is known it would be great help in answering your question.

Save to local drive

I had done a task in which the csv files can be selected using calendar and download form FTP.
At present I had predefined the local drive path to save the csv files.
I need to show pop for save as then the user has to save to any location as they need.
private void Download()
{
System.DateTime myDate = new System.DateTime();
myDate = caldownload.SelectedDate;
System.DateTime myDate1 = new System.DateTime();
myDate1 = Calendar1.SelectedDate;
string sdate;
string edate;
TextBox1.Text = myDate.ToString("yyyy-MM-dd");
TextBox2.Text = myDate1.ToString("yyyy-MM-dd");
DateTime d1 = myDate.Date;
DateTime d2 = myDate1.Date;
TimeSpan sum = d2 - d1;
int NrOfDays = sum.Days;
NrOfDays++;
int k = NrOfDays;
string[] fileName = new string[k];
//increment for days
int s = myDate.Day;
FtpWebRequest reqFTP;
try
{
if (NrOfDays<=7)
{
for (k = 0; k <= NrOfDays; k++)
{
fname[i] = myDate.ToString("yyyy-MM-dd");
fileName[k] = myDate.ToString("yyyy-MM-dd");
//files to save local drive
FileStream outputStream = new FileStream("F:\\ch" + "\\" + fname[i]+".csv", FileMode.Create);
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + "192.162.1.152" + "//" + "[100]" + "//" + fileName[k] + ".csv"));
reqFTP.Method = WebRequestMethods.Ftp.ListDirectory;
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential("", "");
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream ftpStream = response.GetResponseStream();
long cl = response.ContentLength;
int bufferSize = 2048;
int readCount;
byte[] buffer = new byte[bufferSize];
readCount = ftpStream.Read(buffer, 0, bufferSize);
while (readCount > 0)
{
outputStream.Write(buffer, 0, readCount);
readCount = ftpStream.Read(buffer, 0, bufferSize);
}
myDate = myDate.AddDays(1);
ftpStream.Close();
outputStream.Close();
response.Close();
}
}
else
{
ScriptManager.RegisterStartupScript(this, this.GetType(), "message", "alert('You are allowed to download files for maximum of 7 days .');location.href = 'Default.aspx';", true);
}
}
catch (Exception ex)
{ }
}
You can add a SaveFileDialog to retrieve the name of the file from the user.
For example:
string sFileNameToSaveAs = "";
using (var dialog = new SaveFileDialog())
{
dialog.AddExtension = true;
dialog.Filter = "CSV Files (*.csv) | *.csv";
dialog.Title = "Select the file name to save as";
dialog.InitialDirectory = "C:\\";
dialog.CheckPathExists = true;
dialog.DefaultExt = ".csv";
dialog.ValidateNames = true;
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
sFileNameToSaveAs = dialog.FileName;
}
}
if (!string.IsNullOrEmpty(sFileNameToSaveAs))
{
FileStream outputStream = new FileStream(sFileNameToSaveAs, FileMode.Create);
// The rest of your retrieval code goes here
}

Categories