How check max file size upload in C++? - c++

I have a server written in C++, that allow the uploading of files.
But I want to check FIRST, the file size and THEN upload it if it is less than 100 MB, else error.
Is there a function that can do that?
This is my function:
long bytes_read = recv(client_fd, tempBuffer, sizeof(tempBuffer),0);
But I cannot control the var bytes_read while receiving the file, but only after.
This is the problem.

You should to send 4-bytes file length before file data:
int file_fize;
recv(client_fd, &file_fize, sizeof(file_fize),0);
recv(client_fd, buffer, file_fize,0);

You should send the size of the file from a client BEFORE sending the file itself. Check the size and responce to your client if you are ready to receive it or not

Related

When using send() to send data from a text file from client to server through TCP stream, how do I send all the data but only 4 bytes at a time?

Below is an excerpt from my client.cpp file:
//Variables previously declared
char buffer[1024];
char sendbuffer[100];
int sockfd, b;
//Opens specified file
FILE *fp = fopen(argv[3], "rb");
while( (b = fread(sendbuffer, 1, sizeof(sendbuffer), fp)) > 0 )
{
send(sockfd, sendbuffer, b, 0);
}
I am new to client-server programming, and I'm far from being extremely proficient in C++.
When I use the code above, it's successful sending the inf, but it obviously isn't going to send the data 4 bytes at a time.
If I modified the line containing send() as shown below without making other necessary changes, I'm certain that it would be incorrect.
send(sockfd, sendbuffer, 4, 0);
It's also a pain to debug because when I make a change to the code, I have to continuously simulate a client-server interaction, which takes time to set up.
What would be the most efficient way to send this text file data 4 bytes at a time?
Also, can anyone suggest a tool or method for quickly debugging client-server programs?
Let me know if more information is needed. Thanks
Well, you can try to send 4 bytes at a time and it will probably work but you have no control of how many bytes a stream socket will actually send. You have to check the return value.
I do not think you need to debug the program at all. Logging is better because it does not introduce time delays like debugging does, and time is money in the networking world.

c++ asio socket read answer from server

I got simple server-client app.
The idia is:
Client send to server string with sql-request.
Server process the request and send back on client answer with data formated in csv style string.
Everything is already adjusted accept one thing. The problem is to read answer on client cause I don't know the size of recieved string.
Code is bellow:
Server:
std::string answer;
answer = sql_read(*msg); //get the string with data from request
clientSock->write_some(buffer(answer, answer.size())); //send it back on client
Client:
std::string answer;
bytesRead = sock->read_some(boost::asio::buffer(readBuf, inputSize)); //read the answer, but how do I know correct size of string?
string_ptr msg(new std::string(readBuf, bytesRead));
answer = *msg;
How to read the resulting string without knowing its size?
Or if my aproach (with sending data in string) is radically wrong how to do it in correct way?
You must handle this yourself in the protocol the client and server use to speak to each other.
One way is to use a deliminator and use boost::asio::read_until(). Example:
boost::asio::streambuf buf;
boost::asio::read_until (sock, buf, "\r\n"); // or '\0' if zero terminated
Check the Boost.Asio documentation.
Another way is to send the size in an fixed length header before sending the variable length part.
You won't know the size of the string in advance. Where you do the read_some you will need to do a loop to read all the data from the socket. You need to check the number of bytes read and the size of the buffer you allocated. If they are equal then you filled up your read buffer and you need to do another read to check for any remaining data.

Concatenating buffer when the sending is too fast in a socket

I have a socket server receiving XML files each 500ms and sometimes it goes wrong concatenating more than 1 file as only one file.
do
{
char* buf = (char*)MALLOCZ(IP_BUF_SZ);
chrs_read = recv(sockfd, buf, IP_BUF_SZ, 0);
if (chrs_read > 0)
sBuffer.append(buf, chrs_read);
FREE(buf);
buf = NULL;
}
while (chrs_read > 0);
So, sometime chrs_read doesn't return me -1 to stop the receiving and save the file to start a new receiving.
Do I forget some configuration in the socket - it's async and non-blocking by default - and I supposed to keep using this way?
Thank you in advance
The problem is that all files are sent through the same connection, without having a delimiter between them. When the files are sent often, and there is some latency in the network, you can't know where a file ends and a new one begins.
Solutions:
Insert a delimiter between the files, such that you can close the file when you receive the delimiter, and open a new one. Note that the delimiter may be received anywhere inside of buf, or it could even, if the delimiter is longer than one byte, be received partially in one recv call, and the rest follows in the next recv call.
On the sending end, close the connection after sending the file and open a new one for the new file.

C Socket file transfer corrupted data

According to this solution to send out an image through TCP. Since the code is very elegant compared to other ways and both image and file are data, I believe that we can use almost the same code to send out a file.
So if I want to send a file from a client to a server.
On the client side
get file size
send file size
// Above steps will always work, so I will only show code after here
read file content into a buffer
char buf[size];
read(fs,buf,size);
send the buffer
int bytes = 0;
for (uint i = 0;i<size;i+=bytes)
{
if ((bytes = send(sock,buf+i,size-i,0))<0)
{
fprintf(stderr,"Can not send file\n");
close(fd);
return false;
}
fprintf(stderr,"bytes write = %d\n",bytes);
}
And on the server side
recv file size
recv stuff into a buffer with size from step 1
char buf[size];
int bytes=0;
for (uint i = 0;i<size;i+=bytes)
{
if ((bytes = recv(sock,buf+i,size-i,0))<0)
{
fprintf(stderr,"Can not receive file\n");
return false;
}
fprintf(stderr,"bytes read = %d\n",bytes);
}
write buffer to a file
fwrite(buf,sizeof(char),size,fs);
This code will compile and run.
When I send out an cpp binary file(24k) from client to server, since both client and server are on the same machine (OS X), this binary file will be received and can be executed.
But if the server forward the file back to the client, and client forward this file back to the server multiple times, this binary file will be corrupted. But the number of bytes sent and number of bytes received are the same, and the file size is still 24k.
I am wondering what is going wrong here.
Is this an OS bug?
Thanks,
Neither send(), nor recv(), guarantees that the number of bytes requested will actually be sent or received. In that case, the return value will still be positive, but less than the number of bytes that was requested in the system call.
This is extensively documented in the manual page documentation for send() and recv(). Please reread your operating system's documentation for these system call.
It is the application's responsibility to try again, to send or receive the remaining bytes.
This code assumes that the number of bytes that was sent is the number of bytes it requested to be sent. It does appear to handle recv()'s return status properly, but not send()'s. After a fewer number of bytes was sent, this code still assumes that the entire contents were sent or received, and the fwrite() system call will end up writing junk instead of the latter part of the file.
If both client and server are in the same folder, then in this case it is just like copying and pasting a file.
So when client send out a file, it will
open file
get file name/size + send name/size + send data
close file
On the server side,
get file name/size
open the same file again
get file content
close file
So the problem will occur on step 2 by causing a race condition.

Progress bar on file uploading via FTP [C++]

I've written a small program which is able to upload files to a server via ftp. Because of the large size of some files I want to create a progress bar for the user. So during the upload I need to know at certain intervals how many bytes have been sent to the server in order to derive the percentage of the file that has been uploaded. What I have tried so far:
While I call the function FtpPutFile() to upload the file, I spawn a thread with the following code:
hInternet = InternetOpen(NULL,INTERNET_OPEN_TYPE_DIRECT,NULL,NULL,0);
hFtpSession = InternetConnect(hInternet, ftpserver, port, user, pass, INTERNET_SERVICE_FTP, 0, 0);
int filesize = 0; // 2GB max
hFile = FtpOpenFile(hFtpSession,szFileTitle,GENERIC_READ,FTP_TRANSFER_TYPE_BINARY,0);
filesize = FtpGetFileSize(hFile,0);
cout << "Size: " << filesize << endl;
However this doesn't seem to work as filesize keeps returning a value of -1. I think this is due to the fact that I'm writing to a file (uploading part) and at the same time I'm trying to read it to get the file size. And I think this is not possible (please correct me if I'm wrong).
My main question: is there another way to create a progress bar for ftp uploading? Perhaps counting the bytes before they are uploaded using the function readBytesCount() (not sure if this is possible at all).
You want to:
Call InternetSetStatusCallback to set a function that will be called periodically during the transfer.
Pass a (non-zero) value the last parameter to FtpOpenFile. This will be passed back to your status callback function during the transfer.
Then, during the FTP operation, your callback function will be invoked periodically with information about the progress of the transfer, which it can then display to the user.
I don't believe this will let you show actual bytes as they're being transferred though -- if memory serves it mostly shows the discrete steps in a transfer, like opening the handle, resolving names, sending/receiving cookies, and finally closing the handle.
To deal with the actual bytes being written during the transfer of the file itself, you'd typically read a buffer-full of data from the local file, then write that buffer with InternetWriteFile. With that, you can compute the percentage transferred as the number of bytes written so far divided by the total size of the file (and multiply by 100).
Well, I resolved such a problem by sending the file by chunks and updating the progress in place of sending the whole file by one call to FtpPutFile
I mean:
FtpOpenFile(...)
for( ... )
{
InternetWriteFile(... dwChunkSize...)
UpdateProgressBar(dwChunkSize)
}
InternetCloseHandle(...)