Jump to content

  • Log In with Google      Sign In   
  • Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

C++ Win32 Winsock sending a file


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
13 replies to this topic

#1 bennettbugs   Members   -  Reputation: 433

Like
0Likes
Like

Posted 25 February 2012 - 06:32 PM

Ive gotten a few comments on how the people with my game shouldnt have to keep downloading my game from lets say, media fire to get the newest updates. So i made a updater that has a list of files and folders. The host (me) sends the list of files and folders to the client. if the client already has it, then it wont add anything new. but if a folder/file is gone, a new folder is made and files are "downloaded". as in downloaded, i mean sent in chunks. they approach i made is basicly this:

nBuffer is from recv. I open it with the mode binary.


client:
if(std::string(nBuffer)=="FILE_DONE_DOWN")
	{
	 std::cout<<"Finnished Downloading File: "<<this->Files_To_Update[0]<<'\n';
	 this->Files_To_Update.erase(this->Files_To_Update.begin());
	 if(this->Files_To_Update.size()>0)
	 {
	  std::cout<<"Downloading File: "<<this->Files_To_Update[0]<<'\n';
	  this->Send_Client(this->Files_To_Update[0]);
	  this->WriteToFile.open(this->Files_To_Update[0],this->WriteToFile.binary);
	 }
	 else
	 {
	  std::cout<<"Downloading Executable...\n";
	  this->Doing="DOWNLOAD_EXE";
	  this->Send_Client("EXE");
	 }
	}
	else
	{
	 nBuffer[Size]='\0';
	 this->WriteToFile.write(nBuffer,Size);
	 this->Send_Client("OK");
	 std::cout<<nBuffer<<'\n';
	}

host:
if(SendFile.is_open())
	{
	 char SendBuf[Buff_Size];
	 //SendFile.seekg(std::ios::beg+DoingAt*Buff_Size);
	 SendFile.read(SendBuf,Buff_Size);
	 APP.Send_Server(SendBuf,p);
	 DoingAt++;
	 if(SendFile.eof())
	 {
	  SendFile.close();
	 }
	 std::cout<<SendBuf<<'\n';
	}
	else
	{
	 APP.Send_Server("FILE_DONE_DOWN",p);
	 DoingAt=0;
	 SendFile.close();
	 Doing="SEND_FILES";
	}

i dont know if this is right, nor if this is the right approach. i was sort of following this tutorial:
http://www.codeproje...threaded-TCP-se

but instead of using a CFile i just used a fstream.

Oh, and by files i mean .png,.wav,.ogg, etc.

Ad:

#2 hplus0603   Moderators   -  Reputation: 3292

Like
0Likes
Like

Posted 25 February 2012 - 07:23 PM

Does it work? If so, it's probably OK, assuming you give the user proper progress indication, protect against disruptive downloaders on your server, etc.
enum Bool { True, False, FileNotFound };

#3 bennettbugs   Members   -  Reputation: 433

Like
0Likes
Like

Posted 25 February 2012 - 07:39 PM

I really dont know if it works or not. it will start downloading (gibberish, of course) then pause... i know both have to be actively talking to eachother otherwise they both stop, waiting for one to send something when they never will... so as long as i read and write in binary, the files should be ok? i dont know, because you have to have a null terminated string for things... :-\

i really just need to know if this is the right way to read and write any file, and be able to send it.

#4 Cornstalks   Moderator*   -  Reputation: 5362

Like
0Likes
Like

Posted 25 February 2012 - 07:51 PM

Sending a binary file but trying to receive it as a null terminated string will not work. Nor will trying to read a binary file and then send it as a null terminated string. The reason is that the binary data may contain zeros, which would screw everything up. You need to first send the number of bytes of the file (either as a string or as binary data), and then when the client receives this they know exactly how many bytes they need to download and don't have to rely on things being null terminated. When sending data, your Send_Server will have to know how many bytes the chunk is that it's sending. I don't know what p is, but it looks like Send_Server is expecting a null terminated C-style string, and binary data does not fit this description.
[ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

#5 bennettbugs   Members   -  Reputation: 433

Like
0Likes
Like

Posted 25 February 2012 - 07:59 PM

Ah... how would i read/send/write this binary data? or would it be better to read the files as a actual string?

EDIT:

CFile is a file class that allows binary reading and writing, which is what was used in the tutorial. i have 1 more question though: if you read any file from binary, send it, then write it back in binary, will any file work 100%?

#6 hplus0603   Moderators   -  Reputation: 3292

Like
0Likes
Like

Posted 25 February 2012 - 08:59 PM

Sending and receiving blocks of bytes is very similar to using void pointers and memcpy(). As long as you can copy data around with memcpy() and void pointers, you can probably also send and receive it on sockets. Or, for that matter, write data to a file and then read it back.
There are some differences:
- if there's a point inside the block of data, that pointer will mean nothing on the other end
- send() may not send everything you ask it to; recv() may receive less than you asked for
- you need to know how much data is to be received, so you know when the next message starts
enum Bool { True, False, FileNotFound };

#7 bennettbugs   Members   -  Reputation: 433

Like
0Likes
Like

Posted 25 February 2012 - 09:05 PM

Well i just learned that CFile is not included with microsoft visual c++ 2010 express, so that wont work. If you know about window sockets (which you probly do), you have to store the recv in a char-array. so how would i store the recv as binary? and the same with send(), how would i send the binary information?

#8 Cornstalks   Moderator*   -  Reputation: 5362

Like
0Likes
Like

Posted 25 February 2012 - 09:26 PM

You still store it in a char array. And you still send the data from a char array. It's just not a string. There's a difference between a string and a char array. A C-style string is a special type of char array, but a char array is not necessarily a string (it's kinda like how a square is rectangle, but a rectangle isn't necessarily a square). You just can't treat it as a normal C-style string when you send or receive it though. send() and recv() have absolutely no clue what a string is. All they see is binary data. So even when you send/receive a string with them, all the see it as is a plain old binary char array.
[ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

#9 bennettbugs   Members   -  Reputation: 433

Like
0Likes
Like

Posted 25 February 2012 - 10:04 PM

Yeah, i sort of figured that out now. I knew that a string is always null terminated, etc etc... i just now tested with a .txt file, and works well. but when its other files, like .wav s and .png s, it gets buggy. also, i tried getting the file size by doing:
SendFile.open(nMess,SendFile.binary);
std::stringstream LengthBuf;
	  SendFile.seekg(std::ios::end);
	  LengthBuf<<SendFile.tellg();
	  std::cout<<"Sending File Length: "<<LengthBuf.str()<<'\n';
	  SendFile.seekg(std::ios::beg);

and always calls it 2... but otherwise... regular text files work... how would i do this with others?

EDIT:

I found out how to get the size... now i just have to work on the other types of files...

#10 rip-off   Moderators   -  Reputation: 5034

Like
0Likes
Like

Posted 26 February 2012 - 08:16 AM

Is there any reason you are doing this in-band? If you were to host the files on a web server, you could use a simple HTTP library to manage most of this for you. In addition, you might want to separate the updater from the game. Doing this will keep each component simpler.

#11 bennettbugs   Members   -  Reputation: 433

Like
0Likes
Like

Posted 26 February 2012 - 09:59 AM

XD i dont have any money to do anything like that. and if i did, i dont think it would be worth it since no body really plays my game. i mean, if you ever heard of N8, they started kinda like me... but once they started getting players and more money they could spend it on stuff like that. but for now, im trying to do it as easy and free as possible.

#12 bennettbugs   Members   -  Reputation: 433

Like
0Likes
Like

Posted 26 February 2012 - 11:17 AM

Could anyone post some example code for both the client and host that uses fstream to read,send,receive,and write binary files?

#13 rip-off   Moderators   -  Reputation: 5034

Like
0Likes
Like

Posted 26 February 2012 - 12:03 PM

If it works for text files, and not for arbitrary data, then you must be relying on some property in text - an assumption that "binary" data violates. The most obvious example would be assuming that the 0 byte cannot occur in the data. That or accidentally treating the data as if it were a string, for example using the strlen() function.

#14 bennettbugs   Members   -  Reputation: 433

Like
0Likes
Like

Posted 26 February 2012 - 12:58 PM

Nevermind, works perfectly! :D
Im proud of myself.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS