Transfert de fichiers à l'aide de sockets (C#) - fichier reçu ne contient pas de données complètes
J'ai créé un serveur et un client pour un transfert de fichier à l'aide de la connexion socket.
Le problème que je me pose, c'est que le fichier reçu, si sa taille est de plus de 8 KO, est incomplète.
Si vous face à ce problème, pouvez-vous me guider sur de trouver ce que je fais mal (sur le serveur /client)?
Voici les deux méthodes:
Client:
#region FILE TRANSFER USING C#.NET SOCKET - CLIENT
class FTClient
{
public static string curMsg_client = "Idle";
public static void SendFile(string fileName)
{
try
{
//IPAddress[] ipAddress = Dns.GetHostAddresses("localhost");
//IPEndPoint ipEnd = new IPEndPoint(ipAddress[0], 5656);
string IpAddressString = "192.168.1.102";
IPEndPoint ipEnd_client = new IPEndPoint(IPAddress.Parse(IpAddressString), 5656);
Socket clientSock_client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
string filePath = "";
fileName = fileName.Replace("\\", "/");
while (fileName.IndexOf("/") > -1)
{
filePath += fileName.Substring(0, fileName.IndexOf("/") + 1);
fileName = fileName.Substring(fileName.IndexOf("/") + 1);
}
byte[] fileNameByte = Encoding.UTF8.GetBytes(fileName);
if (fileNameByte.Length > 5000 * 1024)
{
curMsg_client = "File size is more than 5Mb, please try with small file.";
return;
}
curMsg_client = "Buffering ...";
string fullPath = filePath + fileName;
byte[] fileData = File.ReadAllBytes(fullPath);
byte[] clientData = new byte[4 + fileNameByte.Length + fileData.Length];
byte[] fileNameLen = BitConverter.GetBytes(fileNameByte.Length);
fileNameLen.CopyTo(clientData, 0);
fileNameByte.CopyTo(clientData, 4);
fileData.CopyTo(clientData, 4 + fileNameByte.Length);
curMsg_client = "Connection to server ...";
clientSock_client.Connect(ipEnd_client);
curMsg_client = "File sending...";
clientSock_client.Send(clientData, 0, clientData.Length, 0);
curMsg_client = "Disconnecting...";
clientSock_client.Close();
curMsg_client = "File [" + fullPath + "] transferred.";
}
catch (Exception ex)
{
if (ex.Message == "No connection could be made because the target machine actively refused it")
curMsg_client = "File Sending fail. Because server not running.";
else
curMsg_client = "File Sending fail." + ex.Message;
}
}
}
#endregion
et Serveur:
#region FILE TRANSFER USING C#.NET SOCKET - SERVER
class FTServer
{
IPEndPoint ipEnd_server;
Socket sock_server;
public FTServer()
{
//make IP end point to accept any IP address with port 5656
//these values will be altered depending on ******* (and/or other ImportSystem)
//this was initially coded, but threw a SocketException on sock.Bind(ipEnd) {Only one usage of each socket address (protocol/network addres/port) is normally permitted}
//ipEnd = new IPEndPoint(IPAddress.Any, 5656);
//
//I'll set it like this (giving the IP through a string)
string IpAddressString = "192.168.1.102";
ipEnd_server = new IPEndPoint(IPAddress.Parse(IpAddressString), 5656);
//
//creating new socket object with protocol type and transfer data type
sock_server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
//bind end point with newly created socket
sock_server.Bind(ipEnd_server);
}
public static string receivedPath = @"C:\Users\Adrian.Constantin\Desktop\Simulare_Forder_Import\";
public static string curMsg_server = "Stopped!";
public void StartServer()
{
try
{
curMsg_server = "Starting...";
sock_server.Listen(100);
curMsg_server = "Running and waiting to receive file.";
Socket clientSock = sock_server.Accept();
byte[] clientData = new byte[512000];
int receivedBytesLen = clientSock.Receive(clientData, SocketFlags.None);
clientSock.ReceiveBufferSize = 8192;
curMsg_server = "Receiving data...";
int fileNameLen = BitConverter.ToInt32(clientData, 0);
string fileName = Encoding.UTF8.GetString(clientData, 4, fileNameLen);
BinaryWriter bWrite = new BinaryWriter(File.Open(receivedPath + "/" + fileName, FileMode.OpenOrCreate)); ;
bWrite.Write(clientData, 4 + fileNameLen, receivedBytesLen - 4 - fileNameLen);
curMsg_server = "Saving file...";
bWrite.Close();
clientSock.Close();
curMsg_server = "Received and Archived file [" + fileName + "]; Server stopped.";
}
catch (SocketException ex)
{
curMsg_server = "File Receving error.";
MessageBox.Show(String.Format("{0} Error cide: {1}", ex.Message, ex.ErrorCode));
}
}
}
#endregion
edit: 24.08.2012 (j'ai réussi à trouver le problème et pour obtenir le serveur de travail)
Code complet pour le serveur est :
SERVEUR:
#region FILE TRANSFER USING C#.NET SOCKET - SERVER
class FTServer
{
IPEndPoint ipEnd_server;
Socket sock_server;
public FTServer()
{
string IpAddressString = "192.168.1.102";
ipEnd_server = new IPEndPoint(IPAddress.Parse(IpAddressString), 5656);
sock_server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
sock_server.Bind(ipEnd_server);
}
public static string receivedPath = @"C:\";
public static string curMsg_server = "Stopped!";
public void StartServer()
{
try
{
curMsg_server = "Starting...";
sock_server.Listen(100);
curMsg_server = "Running and waiting to receive file.";
Socket clientSock = sock_server.Accept();
clientSock.ReceiveBufferSize = 16384;
byte[] clientData = new byte[1024 * 50000];
int receivedBytesLen = clientSock.Receive(clientData, clientData.Length, 0);
curMsg_server = "Receiving data...";
int fileNameLen = BitConverter.ToInt32(clientData, 0);
string fileName = Encoding.UTF8.GetString(clientData, 4, fileNameLen);
BinaryWriter bWrite = new BinaryWriter(File.Open(receivedPath + fileName, FileMode.Append));
bWrite.Write(clientData, 4 + fileNameLen, receivedBytesLen - 4 - fileNameLen);
while (receivedBytesLen > 0)
{
receivedBytesLen = clientSock.Receive(clientData, clientData.Length, 0);
if (receivedBytesLen == 0)
{
bWrite.Close();
}
else
{
bWrite.Write(clientData, 0, receivedBytesLen);
}
}
curMsg_server = "Saving file...";
bWrite.Close();
clientSock.Close();
curMsg_server = "Received and Archived file [" + fileName + "] (" + (receivedBytesLen - 4 - fileNameLen) + " bytes received); Server stopped.";
}
catch (SocketException ex)
{
curMsg_server = "File Receving error.";
MessageBox.Show(String.Format("{0} Error code: {1}", ex.Message, ex.ErrorCode));
}
}
}
#endregion
Vous devez vous connecter pour publier un commentaire.
Vous êtes tombé dans le plus classique piège de la prise de l'utilisation. Celui-ci est aussi vieux que l'idée de sockets développé à Berkely..
Vous voyez, vous n'avez pas lu les docs 🙂
Voir le http://msdn.microsoft.com/en-us/library/ms145160.aspx par exemple - qu'est-ce que la valeur de retour?
À la fois Envoyer et Recevoir les méthodes ne sont pas obligés d'envoyer/recevoir toutes les données que vous avez fournies. C'est pourquoi ils reviennent tous les deux un 'int' décrivant combien a été envoyé/reçu en fait. Cette conception est tenue en raison du système des tampons internes sont limitées. Si vous fournissez un tableau de 999GB à être envoyé, comment le réseau de carte de magasin qui, avant l'envoie?
Vous voyez le comportement de 8KO seuil, probablement parce que c'est la taille de la intenal tampon, ou peut-être la taille maximale d'un réseau TCP packet.. je ne me souviens pas de quelle ampleur ils étaient, mais c'est quelque chose autour de cela.
D'envoyer et de recevoir vos données poperly, vous devez utiliser un type de boucle, par exemple, dans le simplie la forme:
et recv - de la même manière.
De MSDN:
Il n'* garantie de tout lire d'un seul coup; il lit ce qu'il peut jusqu'à le maximum de la taille de la mémoire tampon dans votre cas). Lors de la lecture de tout flux, vous avez généralement besoin d'avoir une Lecture/boucle de réception. Dans votre cas, je dirais que la mémoire tampon est largement surdimensionné, et que vous devriez lire les octets de longueur manuellement, puis il suffit de Lire/boucle de réception sur une petit tampon (par exemple, 4096 octets) pour la gestion des fichiers. Vous n'avez pas besoin d'un 512k de mémoire tampon.
Un classique de Lecture/boucle de réception serait:
Vous avez besoin de délai avant chaque envoi de méthodes d'environ 200 ms, parce que votre tampon de réception est remplacée par les données entrantes.
exemple: