Hilfe bei Bildübertragung per Netzwerk
-
Hi leute,
ich habe die letzten tage versucht ein bild über einen Socket zu senden, doch leider funktioniert das zusammensetzen auf Client-Seite nicht;
Hier ist das zu sendende Bild:
http://img535.imageshack.us/img535/742/testxr.jpg
und hier das, was auf Client-Seite rauskommt:
http://img85.imageshack.us/img85/4955/recvx.jpgIch bin mir sicher das der fehler auf client-seite ist, da das bild auf dem server richtig zerlegt wird.
Es wird vor der Dateiübertragung ein header gesendet der mit "<" und ">" gekennzeichnet ist; in diesem stehen die relevanten informationen (größe,kanäle)Der Epmfangscode sieht folgendermaßen aus:
IplImage *img; int temp_count = 0; bool data_transfer = false; void readHandler(string c, int readBytes) // !!!not thread-safe!!! { if(!data_transfer) { int header_start = c.find("<"); int header_end = c.find(">"); if(header_start==header_end) // normaler text { cout << c; } if(header_start < header_end) { data_transfer = true; int start = c.find("length="); int len = c.find(";",start) - start - 7; // length of number int tcp_out_count = atoi(c.substr(start + 7,len).c_str()); //size start = c.find("width="); len = c.find(";",start) - start - 6; int width = atoi(c.substr(start + 6,len).c_str()); //width start = c.find("height="); len = c.find(";",start) - start - 7; int height = atoi(c.substr(start + 7,len).c_str()); //height start = c.find("depth="); len = c.find(";",start) - start - 6; int depth = atoi(c.substr(start + 6,len).c_str()); //depth start = c.find("channels="); len = c.find(";",start) - start - 9; int channels = atoi(c.substr(start + 9,len).c_str()); //channels img = cvCreateImage(cvSize(width,height), IPL_DEPTH_8U, channels); //TODO: coversion from int depth to valid input } } else { for (int j=0; j<readBytes && j<1024; j++) { img->imageData[temp_count*1024+j] = c[j]; } if(temp_count >= img->imageSize/1024-1) { cout << "<finished>" << endl; cout.flush(); cvSaveImage("recv.jpg",img); temp_count = 0; data_transfer = false; } temp_count++; } }ich hoffe es hat jemand zeit sich das anzusehen;
LG
-
Da die erste Unregelmäßigkeit rechts unten bei einem dunklen Pixel anfängt, gehe ich davon aus, dass es etwas mit der Nullterminierung von string zu tun hat. Du solltest stattdessen vector<unsigned char> verwenden.
Und wenn du so ein Monstrum als Parameter übergibst, solltest du das unbedingt per Referenz machen.
-
Tatsächlich du hattest Recht... es lag wirklich an der null-terminierung von strings (bzw daran das im Bild auch der Wert 0 vorkommt);
Jetzt wird das Bild beim ersten Mal richtig übertragen, beim 2ten mal ist es wieder falsch (http://img534.imageshack.us/img534/8940/recv.jpg) und beim 3ten versuch bekomme ich folgende Antwort:
Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 0xb7fd3b70 (LWP 16935)] 0x0804b512 in readHandler ( c=0xbfffef18 "\"\n\024-\026\024*\027\020:)&?12)\037%\"\032$\036\030#\t\005\021#\037+%\037*\032\022\031\037\024\027\063! $\020\v\027", readBytes=1024) at client.cpp:226 226 img->imageData[temp_count*1024+j] = c[j];Das sieht so aus als obe c nicht die 1024 Bytes sind die es sein sollten, aber ich weiß nicht warum...
Hier nochmal der angepasste code (is nicht schön, aber es muss vorerst tun):
IplImage *img; int temp_count = 0; bool data_transfer = false; void readHandler(char *c, int readBytes) // !!!not thread-safe!!! { //cout << c->length() << endl; if(!data_transfer) { string s(c); int header_start = s.find("<"); int header_end = s.find(">"); if(header_start==header_end) { cout << s; } if(header_start < header_end) { data_transfer = true; int start = s.find("length=",start); int len = s.find(";",start) - start - 7; // length of number int tcp_out_count = atoi(s.substr(start + 7,len).c_str()); //size start = s.find("width="); len = s.find(";",start) - start - 6; int width = atoi(s.substr(start + 6,len).c_str()); //width start = s.find("height="); len = s.find(";",start) - start - 7; int height = atoi(s.substr(start + 7,len).c_str()); //height start = s.find("depth="); len = s.find(";",start) - start - 6; int depth = atoi(s.substr(start + 6,len).c_str()); //depth start = s.find("channels="); len = s.find(";",start) - start - 9; int channels = atoi(s.substr(start + 9,len).c_str()); //channels img = cvCreateImage(cvSize(width,height), IPL_DEPTH_8U, channels); //TODO: coversion from int depth to valid input } } else { for (int j=0; j<readBytes && j<1024; j++) { img->imageData[temp_count*1024+j] = c[j]; } if(temp_count >= img->imageSize/1024-1) { cout << "<finished>" << endl; cout.flush(); cvSaveImage("recv.jpg",img); //tcp_out_count = -1; temp_count = 0; data_transfer = false; } temp_count++; } }und hier die empfangenden funktionen:
void read_start(void) { // Start an asynchronous read and call read_complete when it completes or fails socket_.async_read_some(boost::asio::buffer(buffer, 1024), boost::bind(&tcp_client::read_complete, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } void read_complete(const boost::system::error_code& error, size_t bytes_transferred) { // the asynchronous read operation has now completed or failed and returned an error if (!error) { // read completed, so process the data //buffer[bytes_transferred] = '\0'; //cout << buffer; myPtr(&buffer[0], bytes_transferred); //cout.write(buffer, bytes_transferred); // echo to standard output //cout << "\n"; read_start(); // start waiting for another asynchronous read again } else do_close(); }wobei buffer so definiert ist:
char buffer[1024];LG