A ver, para archivos pequeño he hecho esto y funciona:
Código PHP:
char flagFile[SIZEFLAG] = {"\n\n_File_\n\n\0"};
struct{
char name[256];
long size;
}archivo;
bool recvFile, recvStructFile;
void __fastcall TChatForm::ButtonSendFileClick(TObject *Sender)
{ //Aqui se envia el fichero
long tamanio = 0;
char buffer[SIZEBLOCK];
FILE *hFile;
int enviados = 0, leidos = 0, retval = 0;
if(OpenDialog1->Execute())
{
hFile = fopen(OpenDialog1->FileName.c_str(),"rb");
fseek(hFile, 0, SEEK_END);
tamanio = ftell(hFile);
fseek(hFile, 0, SEEK_SET);
if(hFile)
{
strcpy(archivo.name, ExtractFileName(OpenDialog1->FileName).c_str());
archivo.size = tamanio;
if(IsServer){
retval = ServerSocket->Socket->Connections[0]->SendBuf(flagFile, SIZEFLAG);
retval += ServerSocket->Socket->Connections[0]->SendBuf(&archivo, sizeof(archivo));
}else{
retval = ClientSocket->Socket->SendBuf(flagFile, SIZEFLAG);
retval += ClientSocket->Socket->SendBuf(&archivo, sizeof(archivo));
}
if(retval == (SIZEFLAG + sizeof(archivo)))
{
while(!feof(hFile))
{
//voy por aqui y no funciona
leidos = fread(buffer, sizeof(char), SIZEBLOCK,hFile);
if(IsServer){
retval = ServerSocket->Socket->Connections[0]->SendBuf(buffer, leidos);
}else{
retval = ClientSocket->Socket->SendBuf(buffer, leidos);
}
if(retval != leidos)
{
RichEdit1->SelStart = RichEdit1->Text.Length();
RichEdit1->SelLength = 0;
RichEdit1->SelAttributes->Color = clRed;
RichEdit1->Lines->Add("Error en el envio del fichero");
break;
}else{
enviados += retval;
}
if(ferror(hFile))
{
RichEdit1->SelStart = RichEdit1->Text.Length();
RichEdit1->SelLength = 0;
RichEdit1->SelAttributes->Color = clRed;
RichEdit1->Lines->Add("Error durante la lectura del fichero. Vuelva a intentarlo.");
break;
}
}
}else{
RichEdit1->SelStart = RichEdit1->Text.Length();
RichEdit1->SelLength = 0;
RichEdit1->SelAttributes->Color = clRed;
RichEdit1->Lines->Add("Error inesperado al enviar el archivo.");
}
fclose(hFile);
if(tamanio != enviados)
{
RichEdit1->SelStart = RichEdit1->Text.Length();
RichEdit1->SelLength = 0;
RichEdit1->SelAttributes->Color = clRed;
RichEdit1->Lines->Add("Error en el envio del fichero. El tamaño del fichero original no coincide con el tamaño del fichero enviado.");
}
}
}
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Se produce cuando un socket de cliente debe leer la información de la conexión de socket.
//---------------------------------------------------------------------------
void __fastcall TChatForm::ClientSocketRead(TObject *Sender,
TCustomWinSocket *Socket)
{
// Cuando el servidor envia datos al ciente y este los ha de procesar
unsigned char *buffer;
int size,lenBuff;
lenBuff = Socket->ReceiveLength();
buffer = new char[lenBuff + 1];
memset(buffer,0,sizeof(buffer));
size = Socket->ReceiveBuf(buffer,lenBuff);
if(strcmp(buffer, flagFile) == 0)
{
recvFile = true;
}
else if(recvFile == true && size == (sizeof(archivo.name) + sizeof(archivo.size)))
{
memcpy(archivo.name, buffer, sizeof(archivo.name));
memcpy(&archivo.size, buffer + sizeof(archivo.name), sizeof(archivo.size));
recvStructFile = true;
}else if(recvFile == true && recvStructFile == true){
FILE *salida;
salida = fopen(AnsiString(ExtractFilePath(Application->ExeName) + "\\\\" + archivo.name).c_str(),"wb");
fwrite(buffer, size, 1, salida);
fclose(salida);
}else{
//Si no es una imagen mostramos el mensaje enviado
RichEdit1->SelStart = RichEdit1->Text.Length();
RichEdit1->SelLength = 0;
RichEdit1->SelAttributes->Color = clGreen;
RichEdit1->Lines->Add(EditServer->Text + ": " + AnsiString( (char*)buffer)); // Añadir los datos al memo de recepción
}
delete [] buffer;
}
//---------------------------------------------------------------------------
// Se produce cuando el socket de servidor debe leer la información de un socket cliente.
//---------------------------------------------------------------------------
void __fastcall TChatForm::ServerSocketClientRead(TObject *Sender,
TCustomWinSocket *Socket)
{
// Cuando el cliente envia datos al servidor y este los ha de procesar
unsigned char *buffer;
int size,lenBuff;
lenBuff = Socket->ReceiveLength();
buffer = new char[lenBuff + 1];
memset(buffer,0,sizeof(buffer));
size = Socket->ReceiveBuf(buffer,lenBuff);
if(strcmp(buffer, flagFile) == 0)
{
recvFile = true;
}
else if(recvFile == true && size == (sizeof(archivo.name) + sizeof(archivo.size)))
{
memcpy(archivo.name, buffer, sizeof(archivo.name));
memcpy(&archivo.size, buffer + sizeof(archivo.name), sizeof(archivo.size));
recvStructFile = true;
}else if(recvFile == true && recvStructFile == true){
FILE *salida;
salida = fopen(AnsiString(ExtractFilePath(Application->ExeName) + "\\\\" + archivo.name).c_str(),"wb");
fwrite(buffer, size, 1, salida);
fclose(salida);
}else{
// Cuando el cliente envia datos al servidor y este los ha de procesar
RichEdit1->SelStart = RichEdit1->Text.Length();
RichEdit1->SelLength = 0;
RichEdit1->SelAttributes->Color = clGreen;
RichEdit1->Lines->Add(Socket->RemoteHost + ": " + AnsiString( (char*)buffer)); // Añadir los datos al memo de recepción
}
}
Tiene un problema y es que cuando se hace un SendBuf, al ser asincronico, no espera respuesta y como tarde mas de la cuenta en llegar el bloque, se acumulan y se añaden los bloques unos a otros, o sea, si el primer paquete mide 11 y el segundo mide 260, como tarde mucho en llegar el primero llegara un solo paquete de 271 y asi con todo lo que se envie. Ese es el problema que tengo para poder enviar archivos mas grandes tambien. No se como hacer para que no envie otro paquete hasta que reciba el cliente el anterior y lo procese y asi con todos.