Binary to ASCII

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Binary to ASCII

Post by CuteAlien »

sizeof(buffer) will read 8 bytes (on a 64-bit system) as that's the size of a pointer. As I tried to explain above - you have to send the size of the buffer as well and then allocate that. So you have 2 read and write and send calls (well, you could send them together, but let's keep it easy). First read your header - which must have a fixed size so you know exactly how much to memory to allocate. So for example use this:

Code: Select all

 
struct MyBinaryProtocolHeader
{
 // insteads of irr::u32 and u64 you can also use another type - but be sure it has a fixed size on all platforms
    irr::u32 version; // every protocol should have a version number
    irr::u64 length;  // this is the size of the block that follows
};
 
void receiveFile(SOCKET mySock) {
   MyBinaryProtocolHeader header;
    recv(mySock,(char*)&header, sizeof(MyBinaryProtocolHeader),0);
    char* buffer = new char(header.length);
    recv(mySock,buffer,header.length,0);
 
    std::ofstream myFile ("Test.png", std::ios::binary);
    myFile.write(buffer,header.length);
    myFile.close();
}
 
(not compiled and didn't look up recv header right now, but should be approximately like that)

SendFile has to be rewritten correspondingly, I'll let you do that so it's easier for you to remember how it worked next time you run into this :-)
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
LunaRebirth
Posts: 386
Joined: Sun May 11, 2014 12:13 am

Re: Binary to ASCII

Post by LunaRebirth »

Thanks a TON!
Got it working with that.:)

Soooo excited to move onto important auto-update features, you've got no idea.
Can't express how happy you just made me :D

Thanks again for your expertise help!
LunaRebirth
Posts: 386
Joined: Sun May 11, 2014 12:13 am

Re: Binary to ASCII

Post by LunaRebirth »

Seems the two recv's are getting mixed up. The server is doing send twice, one for the header (length and version) and the second being the buffer (file contents). And the client is recving twice as well. Same order.

I realize it's bad to recv and send more then once per loop, but I'm not sure the most efficient way to do this.
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: Binary to ASCII

Post by mongoose7 »

CuteAlien has assumed the sockets are *blocking*. You can handle the problem simply with

Code: Select all

len = 0;
while (len < size) {
    rv = recv( ... size - len ...);
    if (rv <= 0) break;
    len += rv;
}
A more sophisticated solution relies on more sophisticated methods.
LunaRebirth
Posts: 386
Joined: Sun May 11, 2014 12:13 am

Re: Binary to ASCII

Post by LunaRebirth »

mongoose7 wrote:CuteAlien has assumed the sockets are *blocking*. You can handle the problem simply with

Code: Select all

len = 0;
while (len < size) {
    rv = recv( ... size - len ...);
    if (rv <= 0) break;
    len += rv;
}
A more sophisticated solution relies on more sophisticated methods.
Yes, the server sockets are blocking. The client sockets are not. My current send and recv methods are as follows, and using them does not change my current problem :o

Code: Select all

ssize_t sendAll(int sockfd, const void *buf, size_t len, int flags) {
   ssize_t result;
   char *pbuf = (char *)buf;
   while ( len > 0 ) {
     result = send(sockfd,pbuf,len,flags);
     if ( result <= 0 ) break;
     pbuf += result;
     len -= result;
   }
   return result;
}
 
ssize_t recvAll(int sockfd, const void *buf, size_t len, int flags) {
    u_long iMode=1;
    ioctlsocket(sockfd,FIONBIO,&iMode);
 
   ssize_t result;
   char *pbuf = (char *)buf;
   while ( len > 0 ) {
     result = recv(sockfd,pbuf,len,flags);
     if ( result <= 0 ) break;
     pbuf += result;
     len -= result;
   }
   return result;
}
The reason I think it's mixing the things up is because my server is sending "Incoming file" and the client receives it, then prepares for all incoming files. The server sends all the data stuff it needs.
But my client is creating folders named " ß ß ß ß ß ß ß ß ß ß ß ß ß ß", "@@@ÿ@@@ÿ@@@ÿ", and "kG1ÿkG1ÿ^PHÿ@@@ÿ@@@ÿ@@@ÿ@@@ÿ@@@ÿ@@@ÿ@@@ÿ@@@ÿ@@@ÿ@@@ÿ@@@ÿ" which looks like things that should be in the file itself, not make new folders of the contents. It is creating the correct file(s) at first, though, and saving most of the content in them. And it seems to only happen with larger files
If I try to send a file with 835KB, it screws up like said above.
But sending a file with only 3KB works without any problems what-so-ever
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Binary to ASCII

Post by CuteAlien »

Ugh, sorry - been a long time (we're talking here about decades...) since I last did native socket programming. So recv is supposed to block until you got that much data read in? In that case dosn't look too bad on first view.

Do you allocate enough memory for buf before you call recvAll? (just asking...)

Otherwise I fear I can't be much help with this one.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: Binary to ASCII

Post by mongoose7 »

Well, you haven't shown the send and receive logic. But, then again, I don't want to see it. Let me suggest a way of verifying the data. Let's expand on what CuteAlien has previously said.

Define a 'header' as four bytes:

Byte0: data type, say H_FILENAME, H_FILEDATA, H_MESSAGE
Byte1, Byte2, Byte3: size of data that follows (up to 16MB).

Then, when sending, send the four-byte header followed by the data. When receiving, read the four-byte header. If byte 0 is not one of the defined types, you have made an error. It would also be a good idea to have the high-bit of Byte1 zero (or both high bits) and check for this too. Also, you have to define the buffer to be unsigned char[] or you will get arithmetic errors: unsigned char header[4].
LunaRebirth
Posts: 386
Joined: Sun May 11, 2014 12:13 am

Re: Binary to ASCII

Post by LunaRebirth »

Ah okay! I see. I got it working :P

I made FOR SURE that the client was receiving the proper bytes from the 'header' before continuing to anything. I also made it so while receiving a file, the next recv call doesn't do anything (Which is strange it does, because my recv is blocking and freezing my program exactly like it's blocking) and doing those made it work properly. Thanks again!!
Post Reply