Dateien über Winsock versenden



  • Warum werden denn eigetnlich nur die 1. vier Zeichen empfangen?
    Würde mich auch mal interessieren 🙄



  • was etwas schlecht beschrieben

    mein vorschlag, sende ein stream beginnend mit der der grösse (z.b in size_t) zu senden datei gefolgt mit dem eigendlichen inhalt.

    wenn du mindestens die ersten 4 bytes (siehe (z.b in size_t)) empfangen hast, weißt du an hand der im stream gesendeten bytes, wie gross deine datei ist.

    rc=recv(s,fbuf,1024,0);
    // rc enthält die tatsächlich und in deb buffer geschriebenen bytes
    


  • Also... ich versuch´s mal zu verstehen...
    1. Die Variablen werden deklariert. (Klar)
    2. Die Dateigröße und der Dateiinhalt werden in einem Stream empfangen
    3. Wenn rbuf NULL ist, werden die ersten ? Zeichen von fbuf in n "kopiert".
    Den Rest mit - und + versteh´ ich leider noch net 🙄

    Kann ich den Codeteil denn komplett in mein Projekt übernehmen (oder muss ich doch noch etwas verändern)?

    PS: Wie kann ich denn dann mit den neuen Variablen "CreateFile" aufrufen?
    PPS: Kann ich Dateigröße und Dateiinhalt komplett in einem Stream versenden?
    (oder muss ich da noch ein Trennzeichen setzen?)

    Sorry für die vielen Fragen 😞 bin noch ein Newbie 🙄



  • der codeteil muss natürlich noch erweitert werden

    sollte eine gute anleitung sein http://www.c-worker.ch

    das natürlich auch http://zotteljedi.de/doc/socket-tipps.html



  • Hi vdittrich!
    Wollte eigentlich nur wissen, ob ich zwischen der Dateigröße
    und dem Dateiinhalt noch ein Trennzeichen mitsenden muss. 🙄

    Das mit den Sockets verstehe ich ja schon alles 🙂



  • warum trennzeichen?, du weist duch wie gross die bytes sind.
    du baust ein stream auf wie du es möchtest.

    ganz "grass gesehen"

    struct IO
    {
      int  b1;
      UINT b2;
      char s[255];
    };
    IO   io;
    BYTE x[1024];
    memcpy(x, &io, sizeof(IO));   //sende x;
    
    //empfänger
    BYTE y[1024];                 //empfange y
    IO   out;
    
    memcpy(&out, y, sizeof(IO));
    


  • Also wenn ich zum Beispiel den Inhalt "Halloduda" einer Textdatei sende,
    müsste das so aussehen:

    9Halloduda

    Dem Empfänger müsste ich also "sagen", dass das 1. Zeichen die Dateigröße beinhaltet. Daraufhin liest er die nächsten Zeichen und speichert sie in eine Datei.

    Aber die zu sendende Datei ist ja nicht immer gleich groß! Mal 33KB, mal 55KB...
    Woher soll der Empfänger dann wissen, bis wohin der empfangene Stream die Dateigröße beinhaltet - und ab wo der eigentliche Dateiinhalt beginnt?

    Das geht (meiner Meinung nach) nur mit Trennzeichen 😕
    oder liege ich da falsch? 😞



  • du liegst doch schon richtig.

    //stream
    struct STREAM
    {
      size_t nlen;
      char*  str;
    };
    
    STREAM st;
    
    st.str=/*zeiger auf deine dateiinhalt*/
    st.nlen=strlen(st.str);               //oder anders
    
    //dein strem hat nun die gesamte länge st.nlen+sizeof(size_t)
    //abstrakt gesehen
    
    BYTE buf[1024]; 
    
    size_t pos=0; BYTE* b=buf;
    
    memcpy(b, &st.nlen, sizeof(size_t));
    b +=sizeof(size_t);
    
    while (pos != st.nlen)
    {
      size_t n=1024-(b-buf);
      memcpy(b, str+pos, n);
      // send 1024 bytes
      pos +=n; b=buf;
    }
    

    es gibt natürlich noch viele andere wege, z.b ohne buffer
    man muss aufpassen du kannst nur int=INT_MAX zeichen auf einmal senden

    der empfänger sieht vom prinzip gleich aus

    BYTE buf[1024]; size_t pos=0;
    bool blen=false; 
    STREAM st={0,0};
    
    while (blen && pos != st.nlen)
    {
      int n=recv(0, (char*)buf, 1024, 0);
      if (n == SOCKET_ERROR) break;
      char* b=buf;
      if (!blen)
      {
        // etwas übertrieben man hoft ja auf min 4 byte
        int len= pos+n >= sizeof(size_t)? sizeof(size_t)-pos:n;
        memcpy(&st.nlen+pos, buf, len);
        pos +=len;
        blen= pos != sizeof(size_t);
        if (!blen) continue; 
        // jetzt beginnt das char*
        n -=len; b +=len;
        pos=0;
      }
      if (n)
      {
        //in b mit n bytes steht deine teil (stream) datei
        //den du jetzt mit einem offset von pos wieder in deine 
        //datei schreiben kannst
    
        pos +=n;
      }
    }
    

    was besseres viel mir jetzt auch nicht ein



  • Hi vdittrich!
    Sorry, dass ich noch nicht so viel von dem Code verstehe - bin leider noch ein
    (totaler 😕) Newbie. Die Frage ist mir zwar fürchterlich peinlich 😞
    - aber könntest du mir sagen, wie und wo ich send und CreateFile in dem Code benutzen muss; (und ob ich den Code dann komplett in mein Projekt übernehmen kann)?

    Habe leider noch nicht so viel Ahnung von "memcpy" und "size_t" 🙄

    Vielen, vielen Dank im voraus!
    (Diesmal ohne Rächtschraibfähla 🤡)



  • 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


Anmelden zum Antworten