[C++] Filetransfer via tcp protocol (effiziente netzwerkprogrammierung)

M

mitos

Gast
Hallo!

Also hier mein Problem: Ich wollte mal so was machen wie ftp, also einfach einen server, einen client, und der client kann sich dateien vom server runterladen. Ist mir auch gelungen, übertragung alles hat gut geklappt, ABER die transferraten waren mehr als schlecht -> 2KB/s sobald ich den speed also die größe des auf einmal zu schickenden packetes erhöht habe, hat der client die dateien nur mehr fehlerhaft erhalten...

Ich möchte jetzt sowas machen, dass die transferrate anpasst, also im netzwerk dann 10-20MB/s, im internet eben das was geht.

Hat jemand ein projekt bzw. ein tutorial zum effizienten dateitransfer bzw. einfach einer effizienten verbindung?

Hoffe ihr versteht mein Anliegen, sonst bitte nachfragen.

Vielen dank schonmal.

mfg
mitos
 
Hmm... ziemlich schwer zu sagen so, woran das liegen kann. Ich vermute du benutzt Standard Berkley Sockets? Und auf welcher Plattform entwickelst du?

Wie sieht denn das Protokoll zwischen Client und Server aus? Mal die maximale Send-Buffer-Größe abgefragt?

Ein paar Codeschnipsel helfen vielleicht.
 
Zuletzt bearbeitet:
ja verwende den winsock-socket :) ich entwickle auf windoof xp.

Hier ein paar codeschnipsel:
bei server und client:
Code:
#define MAX_BUFLEN 32000
static char szfilename[] ="bild.jpg";

long laenge;
long buflaenge;
char buffer[MAX_BUFLEN];
char recv_buffer[MAX_BUFLEN];
char readbuf[MAX_BUFLEN];

server:

Code:
case TCP_SOCKET_MSG:
		{
			if (WSAGETSELECTERROR(lParam)) 
				return -1;
			TMP_Socket = (SOCKET)wParam;

			switch (WSAGETSELECTEVENT(lParam))
			{
				case FD_READ:
				{
					ZeroMemory(recv_buffer,MAX_BUFLEN);

			/*		laenge = recv(TMP_Socket, recv_buffer,5,0); //holt sich die länge des kommenden strings

				
					if(laenge<0)
						break;

					recv_buffer[laenge]='\0';
										
					laenge=atoi(recv_buffer);
							
			*/
					buflaenge = recv(TMP_Socket, recv_buffer,MAX_BUFLEN,0);
					
					recv_buffer[buflaenge]='\0';

					/*if(buflaenge!= laenge)
						MessageBox(hWnd,"buflaenge!=laenge","error",0);*/
					if(!strcmp(recv_buffer,"ende"))
					{
						closesocket(TMP_Socket);
					}
					
					if(!strcmp(recv_buffer,"get"))
					{
						//MessageBox(0,0,0,0);
						if(feof(sendfile))
						{
							//send(TMP_Socket,"00008][ende][",13,0);
							int i=4;
							char sbuffer[10];
							char readbuf[5]="%e*[";
							int sended=send(TMP_Socket,readbuf,i,0);
							while(sended!=i)
							{
								for(int j=0; j<(i-sended); j++)
									sbuffer[j]=readbuf[sended+j];

								i=j;
								sended=send(TMP_Socket,sbuffer,i,0);
								strcpy(readbuf,sbuffer);
							}

							fclose(sendfile);
							KillTimer(hWnd,0);
						}
						else
						{

						
					
						for(int i=0; i<(MAX_BUFLEN-6); ++i)
						{
							if(!feof(sendfile))
							readbuf[i]=fgetc(sendfile);
							else
							{i--;
							break;
							}
						}
						
						if(i>=0)
						{
							char sbuffer[MAX_BUFLEN];
							/*
							sprintf(sbuffer,"%05i",i);
							
							for(int j=5; j<(i+5); j++)
								sbuffer[j]=readbuf[j-5];
							
							*/
							int sended=send(TMP_Socket,readbuf,i,0);
							while(sended!=i)
							{
								for(int j=0; j<(i-sended); j++)
									sbuffer[j]=readbuf[sended+j];

								i=j;
								sended=send(TMP_Socket,sbuffer,i,0);
								strcpy(readbuf,sbuffer);
							}
							

						}
						
						}
						}
					
					break;
				}
				case FD_ACCEPT:
				{
					TMP_Socket= accept(TCP_Socket,(SOCKADDR *)&TCPClient,&nSize);					
				
					if(TMP_Socket==INVALID_SOCKET)
						MessageBox(0,"error verbunden",0,0);
					SetTimer(hWnd,0,1000,0);
					 sendfile=fopen(szfilename,"rb");
					if(feof(sendfile))
						{
							//send(TMP_Socket,"00008][ende][",13,0);
							send(TMP_Socket,"%e*[",4,0);
							fclose(sendfile);
							KillTimer(hWnd,0);
						}
						else
						{
						for(int i=0; i<(MAX_BUFLEN-6); ++i)
						{
							if(!feof(sendfile))
							readbuf[i]=fgetc(sendfile);
							else
							{i--;
							break;
							}
						}
						
						if(i>=0)
						{
							char sbuffer[MAX_BUFLEN];
							/*
							sprintf(sbuffer,"%05i",i);
							
							for(int j=5; j<(i+5); j++)
								sbuffer[j]=readbuf[j-5];
							
							*/
							int sended=send(TMP_Socket,readbuf,i,0);
							while(sended!=i)
							{
								for(int j=0; j<(i-sended); j++)
									sbuffer[j]=readbuf[sended+j];

								i=j;
								sended=send(TMP_Socket,sbuffer,i,0);
								strcpy(readbuf,sbuffer);
							}
							

						}
						}
					
					break;
				
					
				}
				case FD_CLOSE:
				{
					closesocket(TMP_Socket);
					break;
				}
			}
			break;
		}

client:
Code:
case TCP_SOCKET_MSG:
		{
			if (WSAGETSELECTERROR(lParam)) 
				return -1;
			TMP_Socket = (SOCKET)wParam;

			switch (WSAGETSELECTEVENT(lParam))
			{
				case FD_READ:
				{
					ZeroMemory(recv_buffer,MAX_BUFLEN);

			/*		laenge = recv(TMP_Socket, recv_buffer,5,0); //holt sich die länge des kommenden strings

				
					if(laenge<0)
						break;

					recv_buffer[laenge]='\0';
										
					laenge=atoi(recv_buffer);
							
			*/
					buflaenge = recv(TMP_Socket, recv_buffer,MAX_BUFLEN,0);
					
					recv_buffer[buflaenge]='\0';

					/*if(buflaenge!= laenge)
						MessageBox(hWnd,"buflaenge!=laenge","error",0);*/
					
					if(recv_buffer[buflaenge-1]=='['&&recv_buffer[buflaenge-2]=='*'&&recv_buffer[buflaenge-3]=='e'&&recv_buffer[buflaenge-4]=='%')
					{
						/*FILE* errorr=fopen("error.txt","wb");
						for(int i=0; i<buflaenge; i++)
							fputc(recv_buffer[i],errorr);
						fclose(errorr);*/

						if(buflaenge>4)
						for(int i=0; i<(buflaenge-4); i++)
							fputc(recv_buffer[i],fcrefile);
						fclose(fcrefile);
						SetWindowText(hWnd,"finito");
						//send(TMP_Socket,"ende",4,0);
					}
					else
					{
						for(int i=0; i<buflaenge; i++)
							fputc(recv_buffer[i],fcrefile);

						send(TMP_Socket,"get",3,0);
						//MessageBox(0,"get",0,0);
					}

					
					
					break;
				}

				case FD_CLOSE:
				{
					closesocket(TMP_Socket);
					break;
				}
			}
			break;
		}

sry für den kranken code, hab ich heute schnell geschriebn :D

mein problem:
die geschwindigkeit passt zwar jetzt, allerdings funktionierts einfach nicht immer, einmal stimmts, einmal wird das bild plötzlich nicht 55,3 (richtige Größe) KB sondern 10MB oder 305 KB, oft gibts auch bildfehler. exe dateien mag er auch nicht. allerdings wenn ich den buffer auf 3200 definiere, funktionierts, (bei .exe dateien aber wieder nicht) also irgendwo muss doch "der hund begraben liegen" !? :confused_alt:

woran kanns liegen?

danke,
mfg
 
Zuletzt bearbeitet:
Hoi.

Also 1., du implementierst kein Protokoll so wie ich das sehe. TCP arbeitet auf Streams, nicht auf Paketen (du weißt nie wann die Datei beginnt und endet, auch wenn mal eine weile nix "reinkommt" auf dem Socket). Ein einfaches Protokoll wäre, zuerst die Dateilänge zu senden (mit htonl kodieren und ntohl dekodieren) und dann die Datei.

2. Die Methode die du verwendest (einzelne Zeichen aus der Datei lesen und einzelne Zeichen zu senden) wird als oft als "painfully slow" bezeichnet. Zum Lesen aus der Datei benutz fread, zum Senden direkt mehr Daten an send übergeben, optimalerweise die Puffergröße, zum schreiben wieder fwrite. send hat auch einen Rückgabewert, den du nicht ignorieren solltest. Die Betriebssystempuffer können vollaufen und send sagt dir dann, dass du es später nochmal versuchen sollst. Das so auf die Schnelle, habe leider keine Zeit, in ein paar Stunden geht's in den Urlaub :)
 
Zurück
Oben