Sign in to follow this  

C++ Win32 Winsock sending a file

This topic is 2116 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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:
[code]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';
}[/code]

host:
[code]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";
}[/code]

i dont know if this is right, nor if this is the right approach. i was sort of following this tutorial:
[url="http://www.codeproject.com/Articles/1922/Beginning-Winsock-Programming-Multithreaded-TCP-se"]http://www.codeproje...threaded-TCP-se[/url]

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

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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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%?

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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:
[code]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);[/code]

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...

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

This topic is 2116 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this