Dateien über Winsock versenden
-
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 sendender 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
-
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.aspso sollte es gehen
MessageBox(NULL, part3.c_str(), "info", MB_OK);
-
Geht leider immer noch nicht

Zu meinem Code:
Ich meinte natürlichif (strcmp(capart, "") != 0) {part3 + apart; count++;}