Client/Server-App mit Sockets...
-
Zunächst mal vielen Dank für deine Hilfe...- hab' mich nun selbst etwas schlau gemacht was die Packet-Grösse betrifft.
Packete bestehen aus einem Header- und einem Data-Field. Das Data-Field ist variabel, was die Grösse betrifft, jedoch mit einer Begrenzung, die MTU (maximum transfer unit) genannt wird. Die MTU beträgt bei Ethernet (wie Du völlig richtig geschrieben hast) 1500 Bytes. D.h. es können nicht mehr als 1500 Bytes an Daten in einem einzigen Packet übertragen werden...
Falls also die Länge einer Nachricht die 1500 Bytes überschreitet (MTU), so wird die Nachricht in mehrere Packete aufgeteilt.
Die Funktion "GetTickCount()", die Du erwähnt hast, werd' Ich mir mal ansehen, ob sie mir bei meinem Problem helfen kann...
-
Eine Frage hätte Ich diesbezüglich noch...- angenommen es werden mehr Daten geschickt als in ein einziges Packet passen (d.h. mehr als 1500 Bytes), dann wird die Nachricht auf mehrere Packete aufgeteilt und schliesslich dann gesendet.
Wie kann der Empfänger jetzt feststellen wann auch wirklich alle Packete (sprich die komplette Nachricht) bei ihm eingetroffen ist???
Wird in dem letzten Packet vielleicht irgendein Flag gesetzt, das andeutet, dass es sich hier um das letzte Packet handelt???
Danke schon mal
-Jackler
-
Hi
Schau dir mal die RFC's zu diesem Thema an. Da steht alles drin was du brauchst.
-
Statt
l_PerfFrequ = uo_PerfCount.l_MyPart / 1000;die Zeile
l_PerfFrequ = uo_PerfCount.l_MyPart / 1000000;verwenden. Und die Anzeige ist in mikrosekunden. Die Auflösung liegt bei ca. 0,8 mikrosekunden.
Ruft man die Funktion 2 mal auf (gleich hintereinander), so hat man auch noch die Eigenverzögerung "gemessen".Bei TCP/IP muß man selbst dafür sorgen, die Länge zu erkennen. Also z.B.: am Anfang einer Message eine Längenfeld definieren und setzten (oder einen Header). Beim Empfang dann die (zerstückelten) Datenbytes mitzählen und zusammensetzen. Auf die Reihenfolge achten, die Pakete können sich auch überholen.
Blackbird
-
Jackler schrieb:
Eine Frage hätte Ich diesbezüglich noch...- angenommen es werden mehr Daten geschickt als in ein einziges Packet passen (d.h. mehr als 1500 Bytes), dann wird die Nachricht auf mehrere Packete aufgeteilt und schliesslich dann gesendet.
Wie kann der Empfänger jetzt feststellen wann auch wirklich alle Packete (sprich die komplette Nachricht) bei ihm eingetroffen ist???
Wird in dem letzten Packet vielleicht irgendein Flag gesetzt, das andeutet, dass es sich hier um das letzte Packet handelt???
Danke schon mal
-JacklerDie Daten werden dann in sogenannte Fragmente zerlegt, deren Größe die jeweilige MTU nicht übersteigt:
- Alle Fragmente des ursprünglichen IP-Pakets erhalten dazu dieselbe Identifikation.
- Für jedes Fragment wird ein IP-Paket erzeugt, in dessen Header das Feld Fragmentoffset die Posotion des Fragments im Original angibt.
- In jedem Paket außer im letzten (!) wird das MF-Flag (More Fragments, Bit 18) auf 1 gesetzt.
- Im IP-Header des letzten Fragments wird das Flag MF auf 0 gesetzt.Die empfangende IP-Schicht muss das Paket aus den Fragmenten reasemblieren (wieder zusammensetzen), bevor es an die Transportschicht weitergegeben wird.
-
hi!
wie schaut das mit der Packetgröße aus, wenn ich eine Datei vom Server zum Client schicken will (zb.: 20-30 MB) damit die möglicht schnell übertragen wird!! gibs da sonst noch was zu beachten??cu
-
Ich beschäftige mich gerade auch damit, wie man am besten große Datenmengen transportieren kann. Zum Transport von Dateien würde ich das FTP-Protokoll vorschlagen. Auf IP-Ebene gibt es die Möglichkeit, den Stack aufzufordern, mit der größtmöglichen MTU zu arbeiten. Dazu benutzt man wohl das Hilfsprotokoll PMTUD (Path MTU Discovery), indem man das DF-Flag (Don't Fragment) setzt.
Wie das aber geht, habe ich noch nicht rausgefunden.
-
Es sit nicht gerade förderlcih die Packte über 1024 zu vergrößern, denn das ist die größe womit ethernet besonder gut arbeiten kann.....
Und was das TCP/IP Protokoll macht, macht es schon lange udn daher halte ich es persönlich gesehen für nicht sinnvoll da zu versuchen da mitzumischen, denn es garantiert einen Grund warum es alles so nutzen wie es ist....(Außer leuten, denen es Spass macht, andere mit nicht korrekten Packeten zu bombardieren)
-
Nox schrieb:
Es sit nicht gerade förderlcih die Packte über 1024 zu vergrößern, denn das ist die größe womit ethernet besonder gut arbeiten kann.....
Und was das TCP/IP Protokoll macht, macht es schon lange udn daher halte ich es persönlich gesehen für nicht sinnvoll da zu versuchen da mitzumischen, denn es garantiert einen Grund warum es alles so nutzen wie es ist....(Außer leuten, denen es Spass macht, andere mit nicht korrekten Packeten zu bombardieren)vielleicht kennst du mirc...warum kann man da die packetgröße von 1024 bis glaube ich 4096 einstellen? ich dachte auch eher an tcp/ip, so wie es halt icq macht!?
cu
-
Nox schrieb:
Es sit nicht gerade förderlcih die Packte über 1024 zu vergrößern, denn das ist die größe womit ethernet besonder gut arbeiten kann.....
Und was das TCP/IP Protokoll macht, macht es schon lange udn daher halte ich es persönlich gesehen für nicht sinnvoll da zu versuchen da mitzumischen, denn es garantiert einen Grund warum es alles so nutzen wie es ist....(Außer leuten, denen es Spass macht, andere mit nicht korrekten Packeten zu bombardieren)Da habe ich aber was anderes gelesen:
Durch die Fragmentierung wird der Verwaltungsaufwand größer, weil mehr Header erforderlich sind und die Reassemblierung durchgeführt werden muss.Von daher wäre es besser, mit der größtmöglichen MTU zu arbeiten. Da die Pakete aber oft über mehrere Teilstrecken mit unterschiedlichen MTUs geführt werden, ist diese nicht unmittelbar feststellbar. Moderne IP-Implementierungen benutzen dazu das Hilfsprotokoll PMTUD (Path MTU Discovery), indem sie das DF-Flag (Don't Fragment, Bit 17) setzen. Sie beginnen mit großen MTU-Werten und erhalten die Fehlermeldung "Fragmentierung notwendig" über das ICMP-Protokoll, dann vermindern sie so lange den MTU-Wert, bis die Fehlermeldungen ausbleiben.
Frage ist nur, ob man überhaupt Einfluss darauf hat, ob es also die Möglichkeit gibt, dies Einstellungen zu ändern.
-
Also ich habe mal vorn nem jahr da nen testbericht gesehen,der eindeutig zeigte das 1024 das beste war.....(ich kenne die config des testsystems aber nicht)
-
#include <winsock2.h> #include <windows.h> #include <stdio.h> #include <conio.h> #include <iostream.h> #include <string.h> #pragma comment( lib, "ws2_32.lib" ) typedef struct _NETFILEHEADER { unsigned long FileSize; char pFileName[256]; } NETFILEHEADER; long SendFileToNet(const char *pFileName, const char *pIP, unsigned short Port) { FILE *pFile; unsigned long FileSize; char buffer[1024]; NETFILEHEADER FileHeader; SOCKET sender; WSADATA wsa; SOCKADDR_IN addr; int addrlen = sizeof(SOCKADDR_IN); pFile = fopen(pFileName, "rb"); if(!pFile) return 0; fseek(pFile, 0, SEEK_END); FileSize = ftell(pFile); fseek(pFile, 0, SEEK_SET); FileHeader.FileSize = FileSize; memset(FileHeader.pFileName, 0, 256); memcpy(FileHeader.pFileName, pFileName, strlen(pFileName)); WSAStartup(MAKEWORD(2,0),&wsa); sender = socket(AF_INET, SOCK_STREAM, 0); memset(&addr, 0, sizeof(SOCKADDR_IN)); addr.sin_family = AF_INET; addr.sin_port = htons(Port); addr.sin_addr.s_addr = inet_addr(pIP); connect(sender, (SOCKADDR*)&addr, addrlen); send(sender, (char*)&FileHeader, sizeof(NETFILEHEADER), 0); while(FileSize >= 1024) { fread(buffer, 1024, 1, pFile); send(sender, buffer, 1024, 0); FileSize -= 1024; } if(FileSize) { fread(buffer, FileSize, 0, pFile); send(sender, buffer, FileSize, 0); } closesocket(sender); fclose(pFile); WSACleanup(); return FileSize; } long GetFileFromNet(unsigned short Port) { SOCKET server; SOCKET client; WSADATA wsa; SOCKADDR_IN addr; char buffer[1024]; long rval; FILE *pFile; NETFILEHEADER FileHeader; long FileSize; int addrlen = sizeof(SOCKADDR_IN); WSAStartup(MAKEWORD(2,0),&wsa); server = socket(AF_INET, SOCK_STREAM, 0); memset(&addr, 0, sizeof(SOCKADDR_IN)); addr.sin_family = AF_INET; addr.sin_port = htons(Port); addr.sin_addr.s_addr = INADDR_ANY; bind(server, (SOCKADDR*)&addr, sizeof(SOCKADDR_IN)); listen(server, 10); client = accept(server, (SOCKADDR*)&addr, &addrlen); //recv(client, (char*)&FileHeader, sizeof(NETFILEHEADER), 0); char *FileHeader1 = new(char[sizeof(Netfileheader)]; unsigned long AlreadyReceived = 0 unsigned long rc = 0; char* p = Fileheader1; do { rc = recv(client, p, sizeof(NETFILEHEADER)-AlreadyReceived, 0); AlreadyReceived += rc; p += rc; }while(AlreadyReceived<sizeof(NETFILEHEADER)); memcopy(FileHeader1, Netfileheader, sizeof(NETFILEHEADER)); FileSize = FileHeader.FileSize; pFile = fopen(FileHeader.pFileName, "wb"); while(FileSize > 0) { rval = recv(client, buffer, 1024, 0); fwrite(buffer, rval, 1, pFile); FileSize -= rval; } fclose(pFile); closesocket(client); closesocket(server); WSACleanup(); return FileHeader.FileSize; } void main(void) { // server: SendFileToNet("net.cpp", "192.168.0.1", 80); // client: GetFileFromNet(80); }hi, hab da das mal mit 1024 probiert! würde ja so passen????
bitte um tipps!cu
-
also ich würde es so machen:
// zuerst den Dateiinhalt auslesen int bytesRead = 0; int bytesTotalRead = FileSize; do { bytesRead = fread(buffer, 1024, 1, pFile); bytesTotalRead -= bytesRead; } while (bytesTotalRead != 0); // senden send(sender, buffer, FileSize, 0);Bei TCP muss du die Pakete nicht selber zerlegen, das macht TCP von alleine.
-
proga schrieb:
also ich würde es so machen:
// zuerst den Dateiinhalt auslesen int bytesRead = 0; int bytesTotalRead = FileSize; do { bytesRead = fread(buffer, 1024, 1, pFile); bytesTotalRead -= bytesRead; } while (bytesTotalRead != 0); // senden send(sender, buffer, FileSize, 0);Bei TCP muss du die Pakete nicht selber zerlegen, das macht TCP von alleine.
ja was ist aber wenn die datei sagn wir 531 kbyte groß ist? da kannst ja wohl kaum immer 1024 nehmen!!!! ja was ist wenn du eine 20MB datei senden willst? dann das mit einem sende() senden ist ja auch net ok?
cu
-
Also er verpackt das nochmal und wenn es ihm von der länge nicht passt sucht er sich selbst was aus. Da kann man halt nciht sicher sein, ob es 100% ist....
-
#include <winsock2.h> #include <windows.h> #include <stdio.h> #include <conio.h> #include <iostream.h> #include <string.h> #pragma comment( lib, "ws2_32.lib" ) typedef struct NETFILEHEADER { unsigned long FileSize; char pFileName[256]; }; long SendFileToNet(const char *pFileName, const char *pIP, unsigned short Port) { unsigned long FileSize; char buffer[1024]; NETFILEHEADER FileHeader; SOCKET sender; WSADATA wsa; SOCKADDR_IN addr; int addrlen = sizeof(SOCKADDR_IN); ////////////// Datei zum Lesen öffnen ////////////////////////// ifstream datei(pFileName, ios::binary); if (!datei) /* Fehler */ return 0; ////////////// Dateigrösse bestimmen /////////////////////////// in_file.seekg (0, ios::end); FileSize = in_file.tellg(); in_file.seekg (0, ios::beg); /////////////// NETFILEHEADER initialisieren /////////////////// FileHeader.FileSize = FileSize; memset(FileHeader.pFileName, 0, 256); memcpy(FileHeader.pFileName, pFileName, strlen(pFileName)); ////////////// Winsock initialisieren ////////////////////////// WSAStartup(MAKEWORD(2,0),&wsa); sender = socket(AF_INET, SOCK_STREAM, 0); memset(&addr, 0, sizeof(SOCKADDR_IN)); addr.sin_family = AF_INET; addr.sin_port = htons(Port); addr.sin_addr.s_addr = inet_addr(pIP); connect(sender, (SOCKADDR*)&addr, addrlen); /////////////////// NETFILEHEADER senden //////////////////////// send(sender, (char*)&FileHeader, sizeof(NETFILEHEADER), 0); /////////////////// Datei senden //////////////////////////////// while(FileSize >= 1024) { in_file.read(buf, 1024); send(sock, buf, stream.gcount(), 0); FileSize -= 1024; } if(FileSize) { in_file.read(buffer, FileSize); send(sock, buffer, stream.gcount(), 0); } /////////////////// Winsock schließen ////////////////////////// closesocket(sender); datei.close(); WSACleanup(); return FileSize; } long GetFileFromNet(unsigned short Port) { SOCKET server; SOCKET client; WSADATA wsa; SOCKADDR_IN addr; char buffer[1024]; long rval; FILE *pFile; NETFILEHEADER FileHeader; long FileSize; ////////////// Winsock initialisieren ////////////////////////// int addrlen = sizeof(SOCKADDR_IN); WSAStartup(MAKEWORD(2,0),&wsa); server = socket(AF_INET, SOCK_STREAM, 0); memset(&addr, 0, sizeof(SOCKADDR_IN)); addr.sin_family = AF_INET; addr.sin_port = htons(Port); addr.sin_addr.s_addr = INADDR_ANY; bind(server, (SOCKADDR*)&addr, sizeof(SOCKADDR_IN)); listen(server, 10); client = accept(server, (SOCKADDR*)&addr, &addrlen); /////////////////// NETFILEHEADER empfangen ///////////////////// char *FileHeader1 = new(char[sizeof(Netfileheader)]; unsigned long AlreadyReceived = 0 unsigned long rc = 0; char* p = Fileheader1; do { rc = recv(client, p, sizeof(NETFILEHEADER)-AlreadyReceived, 0); AlreadyReceived += rc; p += rc; }while(AlreadyReceived<sizeof(NETFILEHEADER)); memcopy(FileHeader1, Netfileheader, sizeof(NETFILEHEADER)); FileSize = FileHeader.FileSize; /////////////////// Datei empfangen ///////////////////////////// ofstream datei(FileHeader.pFileName,ofstream::binary); // In Datei schreiben while(FileSize > 0) { rval = recv(client, buffer, 1024, 0); out_file.write(buf,sizeof(buf)); FileSize -= rc; } /////////////////// Winsock schließen ////////////////////////// datei.close(); closesocket(client); closesocket(server); WSACleanup(); return FileHeader.FileSize; } void main(void) { // server: SendFileToNet("net.cpp", "192.168.0.1", 80); // client: GetFileFromNet(80); }hi, ich hab da mal streams eingebaut!
kann man für den char Buffer auch std::string nehmen fürs send:
send(sock, buf.c_str(), stream.gcount(), 0);funzt das:
ifstream datei(pFileName, ios::binary);verlagt da der 1 param. const char *FileName ??? will da auch lieber std::string nehmen...
beim emfangen des NETFILEHEADER, wie könnte man das besser machen?
cu