File transfer- the file sometimes not full transferred
Hi,
Recently i found out one code from a website. I try to run it, sometimes i can get back the transferred file with original size but sometimes cannot. Some bytes of the file is missing when received it from the server.I unable to open the file that lost some bytes and it shows the file is damaged. This condition is not consistent. I have try many method to find out what problem, but seems like no results for it.Is there any solution to solve this problem?
The code is as below:
Code:
//FILE TRANSFER USING C#.NET SOCKET - SERVER
class FTServerCode
{
IPEndPoint ipEnd;
Socket sock;
public FTServerCode()
{
ipEnd = new IPEndPoint(IPAddress.Any, 5656);
//Make IP end point to accept any IP address with port no 5656.
sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
//Here creating new socket object with protocol type and transfer data type
sock.Bind(ipEnd);
//Bind end point with newly created socket.
}
public static string receivedPath;
public static string curMsg = "Stopped";
public void StartServer()
{
try
{
curMsg = "Starting...";
sock.Listen(100);
/* That socket object can handle maximum 100 client connection at a time & waiting for new client connection /
curMsg = "Running and waiting to receive file.";
Socket clientSock = sock.Accept();
/* When request comes from client that accept it and return new socket object for handle that client. */
byte[] clientData = new byte[1024 * 5000];
int receivedBytesLen = clientSock.Receive(clientData);
curMsg = "Receiving data...";
int fileNameLen = BitConverter.ToInt32(clientData, 0);
/* I’ve sent byte array data from client in that format like [file name length in byte][file name] [file data], so need to know first how long the file name is. /
string fileName = Encoding.ASCII.GetString(clientData, 4, fileNameLen);
/* Read file name */
BinaryWriter bWrite = new BinaryWriter(File.Open(receivedPath +"/"+ fileName, FileMode.Append)); ;
/* Make a Binary stream writer to saving the receiving data from client. /
bWrite.Write(clientData, 4 + fileNameLen, receivedBytesLen - 4 - fileNameLen);
/* Read remain data (which is file content) and save it by using binary writer. */
curMsg = "Saving file...";
bWrite.Close();
clientSock.Close();
/* Close binary writer and client socket */
curMsg = "Reeived & Saved file; Server Stopped.";
}
catch (Exception ex)
{
curMsg = "File Receving error.";
}
}
}
</code>
Code for Client Application:
<code>
//FILE TRANSFER USING C#.NET SOCKET - CLIENT
class FTClientCode
{
public static string curMsg = "Idle";
public static void SendFile(string fileName)
{
try
{
IPAddress[] ipAddress = Dns.GetHostAddresses("localhost");
IPEndPoint ipEnd = new IPEndPoint(ipAddress[0], 5656);
/* Make IP end point same as Server. */
Socket clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
/* Make a client socket to send data to server. */
string filePath = "";
/* File reading operation. */
fileName = fileName.Replace("\\", "/");
while (fileName.IndexOf("/") > -1)
{
filePath += fileName.Substring(0, fileName.IndexOf("/") + 1);
fileName = fileName.Substring(fileName.IndexOf("/") + 1);
}
byte[] fileNameByte = Encoding.ASCII.GetBytes(fileName);
if (fileNameByte.Length > 850 * 1024)
{
curMsg = "File size is more than 850kb, please try with small file.";
return;
}
curMsg = "Buffering ...";
byte[] fileData = File.ReadAllBytes(filePath + fileName);
/* Read & store file byte data in byte array. */
byte[] clientData = new byte[4 + fileNameByte.Length + fileData.Length];
/* clientData will store complete bytes which will store file name length, file name & file data. */
byte[] fileNameLen = BitConverter.GetBytes(fileNameByte.Length);
/* File name length’s binary data. */
fileNameLen.CopyTo(clientData, 0);
fileNameByte.CopyTo(clientData, 4);
fileData.CopyTo(clientData, 4 + fileNameByte.Length);
/* copy these bytes to a variable with format line [file name length][file name] [ file content] */
curMsg = "Connection to server ...";
clientSock.Connect(ipEnd);
/* Trying to connection with server. /
curMsg = "File sending...";
clientSock.Send(clientData);
/* Now connection established, send client data to server. */
curMsg = "Disconnecting...";
clientSock.Close();
/* Data send complete now close socket. */
curMsg = "File transferred.";
}
catch (Exception ex)
{
if(ex.Message=="No connection could be made because the target machine actively refused it")
curMsg="File Sending fail. Because server not running." ;
else
curMsg = "File Sending fail." + ex.Message;
}
}
}
Hope to get help from you all. Thanks.
Regards,
sf
File transfer- the file sometimes not full transferred
Hi,
Thanks for the reply.
Quote:
Originally Posted by
valaris
Code:
int receivedBytesLen = clientSock.Receive(clientData);
and
Code:
clientSock.Send(clientData);
You can't be sure that the server receieves all of the data in one read, or the server sends it all in one write. You probably will want to include in your protocol the length of the file, say the first 4 bytes can say this. Then your server can read in a loop until it gets all these bytes. For the client you just need to make sure you get all the bytes wrote out to write. So do another loop until send has returned all the expected bytes that you are going to send.
I not really sure how to make the server receives all of the data in one read or send it all in one write ? And how to include in the protocol the length of the file? Can somebody give me some guidance? Sorry because i not really very expert in C#, but i need to solve this problem as fast as possible because it is quite urgent for me. Here thank you for help from you all and sorry for my disturbing. Thanks a lot!
Regards,
sf
File transfer- the file sometimes not full transferred
Hi,
Quote:
Originally Posted by
valaris
Well, you have to make up your own protocol for this that the client and server agree on. On your first transmission you can set the first 4 bytes for instance to be the length of the file. Then who ever is receiving can read in a loop until it has received that amount of bytes. This way you are guaranteed to receive all of the file. In C# check out the binary writer/reader for crafting your packets.
If need to set the first 4 bytes to be length of the file, where should i put it? I not really sure for it. Both client server need to set this 4 bytes as well? Any changes do i need to make for binary writer / reader? Sorry for that because i am just a C# beginner. Hope sir can give me some guidance. Thank you very much.
Regards,
sf
File transfer- the file sometimes not full transferred
Hi,
Quote:
Originally Posted by
valaris
Code:
static byte[] GetFileBuffer(string FileName)
{
if (!File.Exists(FileName))
throw new FileNotFoundException("Could Not Find " + FileName);
using (MemoryStream ms = new MemoryStream())
{
using (BinaryWriter br = new BinaryWriter(ms))
{
FileInfo Info = new FileInfo(FileName);
br.Write((int)Info.Length);
br.Write(File.ReadAllBytes(FileName));
//The stream expands as you add bytes, make sure the final buffer
//is the specified size.
ms.Capacity = (int)Info.Length + sizeof(int);
return ms.GetBuffer();
}
}
}
I try this code already but i fail to transfer the file. Is it i need to change something at the server there which is the receiver part? I have no idea on what to change at the receiver part. Is there any hints to it?
Please guide. Thanks!
Regards,
sf
File transfer- the file sometimes not full transferred
Hi, Valaris
I had tried the method that you suggested, the 1st 4 bytes are the file size and the following bytes are file and It help to solve my doubt. :)
However, I found out that the main reason that cause the file transfer incomplete most of the time is due to the socket close by the client before the server able to received all the file. It cause the remaining byte being clear by the client.
Thanks for your help. You help me a lot and i learn a lot from here.
Thank you very much!
Regards,
sf