 |
Cheat Engine The Official Site of Cheat Engine
|
| View previous topic :: View next topic |
| Author |
Message |
oib111 I post too much
Reputation: 0
Joined: 02 Apr 2007 Posts: 2947 Location: you wanna know why?
|
Posted: Sat Jan 10, 2009 2:15 pm Post subject: Sending Files |
|
|
I was wondering how to send files with Winsock. Say you had a basic IM connection like:
| Code: |
Client1 <- -> Server <- -> Client2
|
I know there's the TransmitFile() API, but is this the only way to send files? Because Pidgin for example, has extremely slow transfer rates, while MSN and AIM have moderate transfer rates. Or does it have to do with the nNumberOfBytesPerSend parameter?
_________________
| 8D wrote: |
cigs dont make people high, which weed does, which causes them to do bad stuff. like killing |
|
|
| Back to top |
|
 |
tombana Master Cheater
Reputation: 2
Joined: 14 Jun 2007 Posts: 456 Location: The Netherlands
|
Posted: Sat Jan 10, 2009 2:20 pm Post subject: |
|
|
You could do it manually with winsock: Send some sort of packet indicating your about to send a file, and when you get a positive response from the server, then start sending chunks of the file (waiting for some sort of response to check if it has been sent successfully, maybe a crc check of the packet) and then send a packet indicating the end of the file.
Probably the TransmitFile is a better way of doing it, but I've no idea about speed.
|
|
| Back to top |
|
 |
BanMe Master Cheater
Reputation: 0
Joined: 29 Nov 2005 Posts: 375 Location: Farmington NH, USA
|
Posted: Sat Jan 10, 2009 5:04 pm Post subject: |
|
|
yes Tombana is correct the best way to do it to do it manuely with winsock
flow would be something similiar to this..
start client
Connect to Server
Server sends Description to client as to how big the file is.
Server then breaks file into managable chunks and sends size and number of chunks to client so that client may allocate memory and start a new amount of sockets(delegated by servers response)
the key would be to regroup the file chunks into a file and flush it to disk.
this method would be far faster then any single socket method ;}
hope this helps
regards BanMe
|
|
| Back to top |
|
 |
&Vage Grandmaster Cheater Supreme
Reputation: 0
Joined: 25 Jul 2008 Posts: 1053
|
Posted: Sat Jan 10, 2009 7:58 pm Post subject: |
|
|
| Don't you have to create a file mapping?
|
|
| Back to top |
|
 |
tombana Master Cheater
Reputation: 2
Joined: 14 Jun 2007 Posts: 456 Location: The Netherlands
|
Posted: Sun Jan 11, 2009 7:21 am Post subject: |
|
|
| BanMe wrote: | yes Tombana is correct the best way to do it to do it manuely with winsock
flow would be something similiar to this..
start client
Connect to Server
Server sends Description to client as to how big the file is.
Server then breaks file into managable chunks and sends size and number of chunks to client so that client may allocate memory and start a new amount of sockets(delegated by servers response)
the key would be to regroup the file chunks into a file and flush it to disk.
this method would be far faster then any single socket method ;}
hope this helps
regards BanMe |
I didn't even think of using multiple sockets, never heard of it either. Does that really improve the speed? Won't it just separate the bandwidth over the sockets? But for the other parts, that's the way to do it indeed.
|
|
| Back to top |
|
 |
dnsi0 I post too much
Reputation: 0
Joined: 04 Jan 2007 Posts: 2674
|
Posted: Sun Jan 11, 2009 9:57 am Post subject: |
|
|
Open a connection.
Send a standard HTTP 1.0 header telling that its a multi-part/octostream
or something then send the size of file. Now start sending it in chunks of 1024 bytes
|
|
| Back to top |
|
 |
FerrisBuellerYourMyHero Master Cheater
Reputation: 0
Joined: 14 Feb 2007 Posts: 401 Location: Inside your <kernel>
|
Posted: Sun Jan 11, 2009 4:34 pm Post subject: |
|
|
| _void_ wrote: | | Don't you have to create a file mapping? |
No you don't! Why would you need to create a file mapping? We're not trying to share data with another application (that's called inter-process communication) Instead we want to send a file over the internet using sockets!
| dnsi0 wrote: | Open a connection.
Send a standard HTTP 1.0 header telling that its a multi-part/octostream
or something then send the size of file. Now start sending it in chunks of 1024 bytes |
My way goes like this
| Code: |
Client --> <-- Server
|
Client directly communicates with server, the server is the one hosting the file.
If your making your own server and client you can use any indication to start sending the file, you don't need HTTP protocol...
Here's your problem though, and the same problem as why IM file transferring is slower than it could be. You suggested to use a fixed small buffer size of 1KB. Now think of it this way, the smaller buffer size you use, the more read/write operations have to be done on server and client side! Reading/writing is slow in general.
Lets think of an example...
If you want to transfer a 100MB file, and you use a fixed small 1024 byte(1KB) buffer, you'll have to do 102,400 read operations on server side, and 102,400 write operations on client side.
If instead you up the ante to about 1% of the total file size, and use a 1MB buffer. Now you dramatically reduce the amount of reads/writes to a mere 100 on both ends. sure you'll be updated on the progress of the download less often, but you can live with that for a faster download speed. It's not faster because your transferring the file any faster but because your not spending so much time reading/writing to the file on both server + client side...
This is why IM file transferring is slow. I too was using IM file transferring but then decided to make my own file transferring application using winsock because I knew IM file transferring is slower than it should be. I accomplished my goal and I was able to transfer my files faster by using a bigger buffer!
Coded in C++, I'll post up the source so you can see how its done.
Also if you use a 32bit value to store the file size you wont be able to transfer a file larger than 4.x GB! So I used a 64bit integer to deal with the file size, now you'll be covered for years to come! As I don't think you'd ever want to transfer a file larger than 17179869183.999999999068677425385 GIGABYTES!
Note I made it last year and I had to fix it up a bit, using my newer winsock class and such. It's supposed to support multiple clients connecting and downloading the same file but currently there's a problem I didn't realize when I made it...
Imagine this as an array of sockets, the array goes further but only 5 clients are connected right now
O O O O O
If a client finishes(one from the begging or middle as opposed of the last one) the download and subtracts 1 from the number of clients, that will cause a problem as if a new client connects its socket will overwrite a clients socket that's still in the middle of a transfer. You can see how things will get really messed up.
I'll figure out a solution, but I'll just post it up as it is now, and update it as necessary. Working with Winsock is quite fun actually and I enjoyed making it.
Here's how it works...
You load up the server on the machine you want to send a file from. Before hitting "Start Server", Type in the file path or hit browse to navigate to it. After selecting a file the recommended buffer size (in KB) will be filled in the box. (about 1% of the file) You can change it to be larger if you want, but you'll be updated on progress less often. Password is optional, if you use a password each buffer will be weakly encrypted using the password just for a little security through the pipes. Also each buffer will be decrypted on the client side after recieved, and the clients password has to be correct or they wont receive the file or any info about it. The port is what port you want the server to listen on. It has to be opened on your firewall if you expect the client to be able to connect, and the client has to know the right port. The key is just a randomly generated number to be used as a handshake, if the password is correct(if its used) the server will send the client the handshake and it will have to send it back before the next step happens. The next step is the server will send the client info about the file. File title, size, and the buffer size your using. After the client gets the info the client starts downloading, and the server starts uploading. They have to go in sync, server sends x number of bytes, client receives x number of bytes. That was probably the trickiest part. It just keeps looping through until the whole file is completely transferred...
Here's basically the heart of the uploading/downloading of the file, just so you can get a glimpse here:
//Server Upload
| Code: |
void Upload(int id, SOCKET sock, char* fpath)
{
HANDLE f = CreateFileA(fpath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
char* sendbuffer = new char[MaxBufferSize];
char recvbuffer[4];
int PassLength = strlen(Password);
int i = 0;
DWORD bytesread = 0;
LARGE_INTEGER BytesLeft = {0};
memcpy(&BytesLeft, &filesize64, 8);
while(BytesLeft.QuadPart > 0)
{
if(BytesLeft.QuadPart > MaxBufferSize)
{
ReadFile(f, sendbuffer, MaxBufferSize, &bytesread, 0);
if(Password[0] != 0)
Krypt(sendbuffer, MaxBufferSize, Password); //encrypt buffer with password (if you used one)
sendx(sock, sendbuffer, MaxBufferSize); //send buffer
recvx(sock, recvbuffer, 4); // recieve percentage done
totalsent[id].QuadPart = (filesize64.QuadPart - BytesLeft.QuadPart);
BytesLeft.QuadPart -= MaxBufferSize;
}
else if(BytesLeft.QuadPart <= MaxBufferSize)
{
ReadFile(f, sendbuffer, (DWORD)BytesLeft.QuadPart, &bytesread, 0);
if(Password[0] != 0)
Krypt(sendbuffer, (DWORD)BytesLeft.QuadPart, Password); //encrypt buffer with password (if you used one)
sendx(sock, sendbuffer, (long)BytesLeft.QuadPart);
recvx(sock, recvbuffer, 4);
totalsent[id].QuadPart = (filesize64.QuadPart - BytesLeft.QuadPart);
BytesLeft.QuadPart -= BytesLeft.QuadPart;
}
percent[id] = *(float*)&recvbuffer[0];
}
CloseHandle(f);
percent[id] = 100.0f;
SendMessage(hProg, PBM_SETPOS, (int)percent, 0);
free(sendbuffer);
}
|
Client Download
| Code: |
void Download(char* filename)
{
HANDLE f = CreateFileA(filename, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
char* recvbuffer = (char*)malloc(MaxBufferSize);
int PassLength = strlen(Password) - 1;
int i = 0;
DWORD writtenbytes = 0;
LARGE_INTEGER foffset = {0};
LARGE_INTEGER fullsize = {0};
memcpy(&fullsize, &filesize64, 8);
while(filesize64.QuadPart > 0)
{
if(working == 0)
break;
if(filesize64.QuadPart > MaxBufferSize)
{
recvx(client->serversock, recvbuffer, MaxBufferSize);
sendx(client->serversock, (char*)&percent, 4); // send percent done
if(Password[0] != 0)
Krypt(recvbuffer, MaxBufferSize, Password); //decrypt with password
WriteFile(f, recvbuffer, MaxBufferSize, &writtenbytes, 0);
foffset.QuadPart += MaxBufferSize;
filesize64.QuadPart -= MaxBufferSize;
}
else if(filesize64.QuadPart <= MaxBufferSize)
{
recvx(client->serversock, recvbuffer, (long)filesize64.QuadPart);
sendx(client->serversock, (char*)&percent, 4);
if(Password[0] != 0)
Krypt(recvbuffer, (DWORD)filesize64.QuadPart, Password);
WriteFile(f, recvbuffer, (DWORD)filesize64.QuadPart, &writtenbytes, 0);
foffset.QuadPart += filesize64.QuadPart;
filesize64.QuadPart -= filesize64.QuadPart;
}
percent = ((float)foffset.QuadPart / (float)fullsize.QuadPart) * 100.0f;
SendMessage(hProg, PBM_SETPOS, (int)percent, 0);
}
CloseHandle(f);
free(recvbuffer);
percent = 100.0f;
SendMessage(hProg, PBM_SETPOS, (int)percent, 0);
}
|
_________________
You know, life moves pretty fast. If you don't stop and look around once in a while, You could miss it!
 |
|
| Back to top |
|
 |
oib111 I post too much
Reputation: 0
Joined: 02 Apr 2007 Posts: 2947 Location: you wanna know why?
|
Posted: Sun Jan 11, 2009 9:30 pm Post subject: |
|
|
Thanks Ferris...um...one question. I downloaded the source to both, and I see it's a multi-file project. I never quite got how multi-file projects work (multiple .cpp files, I get .h files).
_________________
| 8D wrote: |
cigs dont make people high, which weed does, which causes them to do bad stuff. like killing |
|
|
| Back to top |
|
 |
FerrisBuellerYourMyHero Master Cheater
Reputation: 0
Joined: 14 Feb 2007 Posts: 401 Location: Inside your <kernel>
|
Posted: Sun Jan 11, 2009 10:38 pm Post subject: |
|
|
| oib111 wrote: | | Thanks Ferris...um...one question. I downloaded the source to both, and I see it's a multi-file project. I never quite got how multi-file projects work (multiple .cpp files, I get .h files). |
well see how it works is like this. Function prototypes are defined in the header file, and the actual function definition is defined in the .cpp file! You include the header file in your main .cpp or wherever you want to use it, and it will find the .cpp file which contains the actual definitions.
In header files that will be included in more than 1 .cpp file it will have to have an include guard
| Code: |
#ifndef EASYSOCKETS_H
#define EASYSOCKETS_H
//the beef of the header file goes here
//function prototypes only
#endif
|
I always go make it the <name of the header file>_H to go along with standards.
It just makes it so you wont get compile errors if you include the header in multiple places...
Its important that you do not put variables in header files that you include multiple places. You'll get errors and it wont work.
However if you notice KryptAndSend.h/KryptAndRecieve.h those header files are only included in the main .cpp file, and therefore don't need the header guard, and can contain variables if you desire to put them there.
So say for example you were making a new project and you wanted to use the winsock class in it. You copy the EasySockets.h and EasySockets.cpp into your project directory. Then add them to your project. Now in your main cpp file or in its header file(like how I do it) you #include "EasySockets.h" (note include EasySockets.h before windows.h, as EasySockets.h includes <winsock2.h> and that must be included before windows.h other wise you'll get errors)
Now that you've done that you can make use of the class from within your main .cpp file
then you can create the xServer, or xClient objects for use in your program.
I too used to be confused about multi-file projects, and use to just cram everything in header files lol. Just remember prototype in header, definition in .cpp, and include guards when necessary.
If you follow that standard you can never go wrong.
_________________
You know, life moves pretty fast. If you don't stop and look around once in a while, You could miss it!
 |
|
| Back to top |
|
 |
oib111 I post too much
Reputation: 0
Joined: 02 Apr 2007 Posts: 2947 Location: you wanna know why?
|
Posted: Sun Jan 11, 2009 10:47 pm Post subject: |
|
|
Ok, thanks, that clears it up a lot
_________________
| 8D wrote: |
cigs dont make people high, which weed does, which causes them to do bad stuff. like killing |
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum
|
|