Dateien über Winsock versenden



  • ich denke du solltest dich erst mal mit was einfacheren beschäftigen.

    bei http://zotteljedi.de/doc/socket-tipps.html kannst du dir den kompl. source eines ftp-socket runterladen, das ist doch das was du suchst.

    fertige lösungen wirst du von keinen hier bekommen.



  • Hab ich mir schon gedacht, dass man hier keine fertigen Codes bekommt 🙄

    Es ist doch praktisch möglich, die Datei und die Dateigröße getrennt mit einem | in einem Stream an den Server zu senden.

    Um die Datei und die Dateigröße jeweils in einem String abzuspeichern, kann ich doch dann eine "selbstgeschriebene" 😃 explode - Funktion benutzen:

    std::string explode(char trennzeichen, std::string str, int part)
                       {
                         std::string output;
                          if (part == 0) // Wenn der erste Part gesucht wird
                                         // müssen viele komplizuierte schritte nicht gemacht werden
                             {
                                  string::size_type pos1 = str.find_first_of(trennzeichen);
                                  output = str.substr(0,pos1);
                             }
                             else
                             {
                                 /* Als erstes muss die Anzahl der Trennzeichen in dem
                                    zu Teilendem String festgestellt werden, dies geschieht in
                                    einer Schleife, und wenn die Anzahl (int i) mit (int) part (-1)
                                    übereinstimmt wird die Postition ausfindig gemacht.
                                 */
                                 int s_lengh = strlen(str.c_str());
                                 int match_c = 0;
    
                                 for (int i=0;i<s_lengh;i++)
                                     {
    
                                       if (str[i] == trennzeichen)
                                          {
                                           match_c++;
                                            if (match_c == part)
                                               {
                                                 std::string str_2 = str.substr(i+1, 1000);
                                                 string::size_type pos2 = str_2.find_first_of(trennzeichen);
                                                 output = str_2.substr(0,pos2);
                                               }
                                          }
                                     }
                             }
                         return output;
                       }
    

    ... oder nicht?



  • Wozu so umständlich? Wenn du die Dateigröße direkt als int am Anfang überträgst sind das doch immer 4 Bytes 😉



  • Wirklich? Na, wenn das so ist 🙂
    - Aber mit welchen Funktionen (die nicht so kompliziert sind 🙄)
    kann ich denn dann meinen empangenen Buffer "auseinander nehmen"?



  • Du liest einfach das erste Byte aus (und wandelst es wieder in einen int um - anschließend setzt du den Pointer um einen Byte weiter 🙂



  • Schaue dir das mal an

    //receiver
    	while (ret != SOCKET_ERROR)
    	{
    		ret = recv (*connectedSocket, Buffer,(2*sizeof(int)),NULL);
    
    		if(ret == (2*sizeof(int)))
    		{
    			memcpy(&iCommandNr,Buffer,sizeof(int));
    			memcpy(&iRecBufferSize,&Buffer[sizeof(int)],sizeof(int));
    			cRecBuffer = new char[iRecBufferSize];
    
    			if(0 != iRecBufferSize)
    				recv (*connectedSocket, cRecBuffer,iRecBufferSize,NULL);
    
    			wsprintf(port,"%d",*connectedSocket);
    			iPos = m_This->m_listL.InsertItem(0,port);
    			m_This->SetLVMStructureL(iPos,1,cPlayerName);
    			m_This->SetFunctionName(iCommandNr,iPos);
    
    			m_This->cManagerServer.SendBuffer(iCommandNr,iRecBufferSize,cRecBuffer,&cSendBuffer,port);
    
    			delete [] cRecBuffer;
    			char * SendeBuffer;
    			char indicator = -1;
    			SendeBuffer = new char [((2*sizeof(int))+iRecBufferSize)+1];
    			memcpy(SendeBuffer,&iCommandNr,sizeof(int));
    			memcpy(&SendeBuffer[sizeof(int)],&iRecBufferSize,sizeof(int));
    			memcpy(&SendeBuffer[(2*sizeof(int))],cSendBuffer,iRecBufferSize);
    			memcpy(&SendeBuffer[(2*sizeof(int))+iRecBufferSize],&indicator,1);
    
    			send(*connectedSocket,SendeBuffer,(2*sizeof(int)), NULL);
    
    			int iSendData = 0;
    			int icount = 0;
    			int i = 0;
    			int ISize = iRecBufferSize+1;
    			bool bFirst = true;
    			do
    			{
    				if(1024 < (iRecBufferSize-icount))
    					iSendData = 1024;
    				else
    					iSendData = ISize-icount;
    				char szData = 1;
    				do
    				{
    					i = send(*connectedSocket,&SendeBuffer[(2*sizeof(int))+icount],iSendData, NULL);
    					ret = recv (*connectedSocket, Buffer,1,NULL);
    					if(ret != -1)
    						memcpy(&szData,Buffer,1);
    				}while(szData == 1 && ret != SOCKET_ERROR && ret != 0);
    
    				if(bFirst && i != 0)
    				{
    					bFirst = false;
    					icount--;
    				}
    				icount += i;
    				if(i == 0)
    					icount--;
    			}
    			while(icount != iRecBufferSize && ret != SOCKET_ERROR && ret != 0);
    			delete [] SendeBuffer;
    			delete [] cSendBuffer;
    			if(FSetClientName == iCommandNr)
    			{
    				CString ctmp;
    				ctmp = m_This->cManagerServer.GetClientName(port);
    				strcpy(cPlayerName,ctmp.GetBuff(ctmp.GetLength()));
    				ctmp.ReleaseBuffer();
    			}
    			continue;
    		}
    
    		if (ret == 0 || ret == SOCKET_ERROR)
    		{
    		}
    	}
    
    //Sender
    DLLEXPORT virtual void Send(int ifunctionNo,int &ISize,char *cSendBuffer,char **cRecBuffer)
    	{
    		char * TransmitBuffer;
    
    		TransmitBuffer = new char[(2*sizeof(int)+ISize)];
    
    		memcpy(TransmitBuffer,&ifunctionNo,sizeof(int));
    		memcpy(&TransmitBuffer[sizeof(int)],&ISize,sizeof(int));
    		memcpy(&TransmitBuffer[(2*sizeof(int))],cSendBuffer,ISize);
    
    		if(0 > send(ssocket, TransmitBuffer,((2*sizeof(int))+ISize),NULL))
    		{
    			bConnected = false;	
    		}
    		else
    		{
    			char sbuffer[8];
    
    			recv (ssocket,sbuffer,(2*sizeof(int)), NULL);
    
    			memcpy(&ifunctionNo,sbuffer,sizeof(int));
    			memcpy(&ISize,&sbuffer[sizeof(int)],sizeof(int));
    			ISize++;
    
    			if(0 < ISize)
    			{
    
    				*cRecBuffer = new char[ISize];
    				char indicator = -1;
    				char *ptemp ;
    				int i = 0;
    				int icount = 0;
    				int iReaddata = 0;
    				int iSendData = 0;
    				bool bFirst = true;
    
    				memset(*cRecBuffer,0,ISize);
    
    				char *tmp = new char [ISize];
    				do
    				{
    					indicator = -1;
    					if(1024 < (ISize-icount))
    						iReaddata = 1024;
    					else
    					{
    						if( 0 == icount)
    							iReaddata = ISize-icount;
    						else
    							iReaddata = ISize-icount;
    					}
    					char *crecievebuffer = new char[iReaddata];
    					memset(crecievebuffer,0,iReaddata);
    					i = recv(ssocket,crecievebuffer,iReaddata,NULL);
    					if(i == -1)
    					{
    						indicator = 1;
    						i = WSAGetLastError();
    						i = 0;
    					}
    					while(-1 == send(ssocket, &indicator,1,NULL));
    					memcpy(&tmp[icount],crecievebuffer,i);
    
    					if(bFirst && i != 0)
    					{
    						bFirst = false;
    						icount--;
    					}
    					icount +=i;
    					if(i == 0)
    						icount--;
    					ptemp = tmp;
    					delete [] crecievebuffer;
    
    				}while(ptemp[icount] != -1);
    				memcpy(*cRecBuffer,tmp,ISize);
    				delete [] tmp;
    			}
    		}
    		delete [] TransmitBuffer;
    	};
    

    So mache ich es in einem TCP Server von mir

    edit: sfds



  • Igitt!!! Wie wär's mal mit Code-Tags???



  • Sorry werde ab jetzt code-tags verwenden .
    Danke ichbins



  • OK - hab den Filetransfer jetzt doch mit der selbstgeschriebenen explode-Funktion geschafft. Allerding klappt das ganze nur bis zum 1. "|" Zeichen in der Gif-Datei. Da ja in so einer GIF-Datei alle möglichen Buchstaben und Zeichen vorkommen, weis ich leider net, welches Zeichen ich als Trennzeichen benutzen kann. 😕



  • Habe eine Lösung gefunden!
    Bin gerade dabei, eine while-Schleife zu programmieren, die überprüft, ob noch mehr Zeichen nach dem | kommen.

    (So in etwa):

    char * abort = "no"; int count = 2;
    while (abort == "no")
    {
    	String part[count] = explode('|', buf, count);
    	const char * cpart[count] = part[count].c_str();
    
    	if (strcmp(cpart[count], "") == 0) {abort = "yes";}
    	else {part1 + cpart[count]; count++;}
    }
    

    Natürlich ist der Code völlig falsch 🙄
    Aber wie kann man eigentlich Strings nach so einem Prinzip erstellen lassen?
    Ihr wisst hoffentlich, was ich meine 🙄



  • @ichbins17: hast du einen tcp server geproggt? kannst du mir eventuell mal die source geben: surfman19@gmx.at

    wär klass...
    cu



  • Hi @all!
    Habe es jetzt mit folgendem Code realisiert. Das Problem ist nur, dass keine Messagebox ausgegeben wird 😞

    int count = 3; char * abort = "no";
    			string part1 = explode('|', buf, 0);
    			string part2 = explode('|', buf, 1);
    			string part3;
    
    			const char * checkfile = part1.c_str();
    			const char * cfilesize = part2.c_str();
    
    			while (strcmp(abort, "no") == 0)
    			{
    				string apart = explode('|', buf, count);
    				const char * capart = apart.c_str();
    
    				if (strcmp(capart, "") != 0) {part3 + capart; count++;}
    				else {abort = "yes";}
    			}
    
    			const char * data = part3.c_str();
    			MessageBox(NULL, data, NULL, NULL);
    


  • deine messagebox weis nicht was sie tun soll (letzter parameter)
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/dialogboxes/dialogboxreference/dialogboxfunctions/messagebox.asp

    so sollte es gehen

    MessageBox(NULL, part3.c_str(), "info", MB_OK);
    


  • Geht leider immer noch nicht 😞

    Zu meinem Code:
    Ich meinte natürlich

    if (strcmp(capart, "") != 0) {part3 + apart; count++;}
    


  • wenn du schon std::string benutz kannst du doch auch die einbauten funktionen benutzen siehe http://cplus.kompf.de/artikel/strings.html
    warum machst du abort nicht boolisch ?

    probiert es mal so
    [cpp]
    while (strcmp(abort, "no") == 0)
    {
    string apart = explode('|', buf, count);

    if(apart.compare("") != 0) // oder apart.size() > 0
    {
    part3 += apart;
    ++count;
    }
    else
    abort = "yes";

    }

    MessageBox(NULL, part3.c_str(), "info", MB_OK);
    [/cpp]



  • Geil! Es klappt endlich!
    Vielen Dank für die schnelle Antwort und den Codeschnipsel!
    Nach dem letzten Zeichen erscheint in der Messagebox zwar noch ein bisschen Müll - aber das bekomm´ ich bestimmt auch noch hin 😃 🙄

    THX Maxime

    Achja - bevor ich´s vergesse:
    VIELEN DANK AN ALLE, DIE AUF MEINE FRAGEN GEANTWORTET HABEN!
    IHR HABT MIR SEHR WEITERGEHOLFEN! 👍



  • 😡 ...Jaja... der Filetransfer klappt - aber leider nur bei kleinen Textdateien 😞 Bei Gif oder PNG-Dateien sieht das ganze dann in etwa so aus:

    ‰PNG
    
     ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍýýýýÝÝÝQ   ±   °œ P› ÀsB ¶   €         ýýýý @  @ `Q@ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍýýýý    ±   1      Àœ $~B             ýýýýÿÿÿÿÁ
    ÍÍÿÿÿÿÁ
    ÍÍÿÿÿÿÁ
    ÍÍÿÿÿÿ
    

    😞
    Ich seh´ mich echt schon in ein paar Wochen mit ´nem FTP-Server hantieren 😞 😕



  • Hi!
    Ich könnte die Datei allerdings noch "binär" auslesen und sie in Einzelteilen versenden - aber ich habe
    noch keine Ahnung wie ich das anstellen soll 🙄

    crazychicken (alias "Maxime")

    PS:
    Kennt vielleicht jemand von euch ein gutes Tutorial über "Dateien über Winsock versenden"? Ich bin jetzt nämlich bei meinem Projekt so ziemlich mit meinem Latein am Ende 🙄



  • HANDLE fileHandle;
    DWORD fileSize;
    DWORD bytesRead;
    char *sendeBuffer;
    
    // Datei öffnen:
    fileHandle=CreateFile("test.gif",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
    
    // Dateigröße holen:
    fileSize=GetFileSize(fileHandle,NULL);
    
    // Speicher für die Datei und die Längenangabe holen:
    sendeBuffer=(char*)malloc( fileSize+sizeof(DWORD) );
    
    // Länge in den sendeBuffer kopieren:
    memcpy(sendeBuffer,(void*)&fileSize,sizeof(DWORD));
    
    // Datei hinter die Längenangabe in den sendeBuffer einlesen:
    ReadFile(fHandle,sendeBuffer+sizeof(DWORD),fileSize,&bytesRead,NULL);
    
    // DateiHandle schließen:
    CloseHandle(fileHandle);
    
    // Daten über Winsock senden:
    send(zielSocket,sendeBuffer,(fileSize+sizeof(DWORD)),0);
    
    // Speicher freigeben:
    free(sendeBuffer);
    

    So ungefähr würde ich das senden machen, also quasi erst senden wieviele Bytes kommen (einfach einen DWORD schicken) und direkt danach eben die komplette Datei binär rübersenden...



  • Vielen Dank für das Codebeispiel!
    Werde es (sobald ich Zeit habe) mal so ausprobieren.
    Vielleicht klappt´s ja dann 👍

    PS: Man könnte doch mal ein Beispiel der Dateiübertragung über Winsock in die FAQ´s stellen, oder? (Ist nur ein Vorschlag ;))

    crazychicken 🙂


Anmelden zum Antworten