Lesen die gesamte Datei aus und senden es per sockets
Machte ich einen server und einen client, der sollte die übertragung von Dateien.
Ich habe versucht, es Lesen die gesamte Datei aus und senden Sie es.
Aber jetzt, da ich sehe es, ich habe ein problem.
Server sollte automatisch die Datei senden, wenn der client verbunden ist.
Aber die Datei ist leer, und ich weiß nicht, wo das problem ist
Sie können sehen, dass ich versuche, zu senden .txt-Datei. Aber ich würde gerne in die Zukunft senden einer großen Datei, aber nicht größer als 1 MB sein.)
Edit:
Bild hier: http://img819.imageshack.us/img819/8259/aadi.jpg
- Links: Die Datei, die ich versuchte, Sie zu senden.
- Rechten Seite: die Datei, Die ich erhielt
Das Problem: Die Datei, die ich erhielt, wurde beschädigt, und ich kann es nicht verwenden.
Server:
#include <WinSock2.h>
#include <Windows.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#pragma comment(lib, "Ws2_32.lib")
#define Port 6000
SOCKET Socket, Sub;
WSADATA Winsock;
sockaddr_in Addr;
sockaddr_in IncomingAddress;
int AddressLen = sizeof(IncomingAddress);
int main()
{
WSAStartup(MAKEWORD(2, 2), &Winsock); //Start Winsock
if(LOBYTE(Winsock.wVersion) != 2 || HIBYTE(Winsock.wVersion) != 2) //Check version
{
WSACleanup();
return 0;
}
Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ZeroMemory(&Addr, sizeof(Addr));
Addr.sin_family = AF_INET;
Addr.sin_port = htons(Port);
bind(Socket, (sockaddr*)&Addr, sizeof(Addr));
if(listen(Socket, 1) == SOCKET_ERROR)
{
printf("listening error\n");
}
else
{
printf("listening ok\n");
}
if(Sub = accept(Socket, (sockaddr*)&IncomingAddress, &AddressLen))
{
char *ClientIP = inet_ntoa(IncomingAddress.sin_addr);
int ClientPort = ntohs(IncomingAddress.sin_port);
printf("Client conncted!\n");
printf("IP: %s:%d\n", ClientIP, ClientPort);
printf("Sending file .. \n");
FILE *File;
char *Buffer;
unsigned long Size;
File = fopen("C:\\Prog.rar", "rb");
if(!File)
{
printf("Error while readaing the file\n");
getchar();
return 0;
}
fseek(File, 0, SEEK_END);
Size = ftell(File);
fseek(File, 0, SEEK_SET);
Buffer = new char[Size];
fread(Buffer, Size, 1, File);
char cSize[MAX_PATH];
sprintf(cSize, "%i", Size);
fclose(File);
send(Sub, cSize, MAX_PATH, 0); //File size
//int len = Size;
//char *data = Buffer;
int Offset = 0;
while(Size > Offset)
{
int Amount = send(Sub, Buffer + Offset, Size - Offset, 0);
if(Amount <= 0)
{
cout << "Error: " << WSAGetLastError() << endl;
break;
}
else
{
Offset += Amount;
printf("2\n");
}
}
free(Buffer);
closesocket(Sub);
closesocket(Socket);
WSACleanup();
}
getchar();
return 0;
}
Client:
#include <WinSock2.h>
#include <Windows.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#pragma comment(lib, "Ws2_32.lib")
SOCKET Socket;
WSADATA Winsock;
sockaddr_in Addr;
int Addrlen = sizeof(Addr);
int main()
{
WSAStartup(MAKEWORD(2, 2), &Winsock); //Start Winsock
if(LOBYTE(Winsock.wVersion) != 2 || HIBYTE(Winsock.wVersion) != 2) //Check version
{
WSACleanup();
return 0;
}
Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ZeroMemory(&Addr, sizeof(Addr)); //clear the struct
Addr.sin_family = AF_INET; //set the address family
Addr.sin_addr.s_addr = inet_addr("127.0.0.1");
Addr.sin_port = htons(6000); //set the port
if(connect(Socket, (sockaddr*)&Addr, sizeof(Addr)) < 0)
{
printf("Connection failed !\n");
getchar();
return 0;
}
printf("Connection successful !\n");
printf("Receiving file .. \n");
int Size;
char *Filesize = new char[1024];
if(recv(Socket, Filesize, 1024, 0)) //File size
{
Size = atoi((const char*)Filesize);
printf("File size: %d\n", Size);
}
char *Buffer = new char[Size];
//int len = Size;
//char *data = Buffer;
int Offset = 0;
while(Size > Offset)
{
int Amount = recv(Socket, Buffer + Offset, Size - Offset, 0);
if(Amount <= 0)
{
cout << "Error: " << WSAGetLastError() << endl;
break;
}
else
{
Offset += Amount;
printf("2\n");
}
}
FILE *File;
File = fopen("Prog.rar", "wb");
fwrite(Buffer, 1, Size, File);
fclose(File);
getchar();
closesocket(Socket);
WSACleanup();
return 0;
}
- Ist die Größe der Datei kodiert als ein 1.024-byte-string? Oder ein
MAX_PATH
byte-string? Und was passiert, wenn der ersterecv
bekommt, sagen wir, 31 bytes? Sie implementiert ein sane-Protokoll für das senden der Daten, aber du hast vergessen zu sein, ebenso vorsichtig, wie Sie das senden der Datei Größe.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den
send
API können nicht senden Sie alle Daten, die Sie angefordert zu senden. Also, Sie haben, um die Aufmerksamkeit auf die return-Wert an, und wiederholen Sie das senden von wo aus die letzten senden beendet. Als Beispiel:Während Sie etwas ähnliches für Ihre Datei übertragen, die Sie nicht machen sicher, dass dies der Fall für die Dateigröße.
Beim senden der Datei die Größe, Sie müssen nur senden Sie die Zeichenfolge, die für die Größe, nicht die gesamte
MAX_PATH
. Der Empfänger muss dann ermitteln Sie die erste Zeichenfolge, um die Größe zu bestimmen, aber keine Daten Lesen nach dem Ende des ersten string muss als Teil der Datei. Aber, da Sie versuchen, die sendenMAX_PATH
ist, sollte der Empfänger erhalten den gleichen Betrag. Ihrem client-code erhält, 1024 bytes, aber es gibt keinen Hinweis dies ist die gleiche Größe wieMAX_PATH
.Den
recv
API kann auch wieder weniger bytes als angefordert. Verwenden Sie eine Schleife zu behandeln Lesen der Datei, aber Sie müssen eine Schleife zum Lesen der gesamten Nachricht, die enthält die Größe der Datei.In Ihrem client erhalten-Schleife, Sie erhöht die
data
Zeiger. Dies macht es unbrauchbar zu schreiben, die die Datei später. Sie haben bereitsBuffer
obwohl, so verwenden Sie, um schreiben Sie Ihre Datei.Wenn Sie auf einen Fehler stoßen dabei socket-I/O, erhalten Sie die Fehlermeldung mit
WSAGetLastError()
, oder Sie können die Ausgabegetsockopt()
auf die Buchse mit derSO_ERROR
option. Können diese unterschiedliche Werte zurückgeben, aber der Grund, korreliert werden sollte.MAX_PATH
hat den gleichen Wert wie1024
?Mich vor dem gleichen problem und nach googeln gefunden, dass die send () - api senden können maximal Daten basierend auf low-level-TCP-Puffer, die sind os-abhängig.Also, inorder, um eine riesige Datei, die wir brauchen, um eine Datei Segmentierung , dh senden der Datei in der form von Blöcken.
Auf dem empfangenden Ende müssen wir recv () - api aufgerufen, bis der gesamte Inhalt der Datei gelesen wird.
credits:shacktar cplusplus.com