download a file using C Socket Programming - c

I need to transfer .txt file using sockets. I try this:
Server:
#define CHUNKSIZE 1024
FILE* fd = fopen("download.txt", "rb");
size_t rret, wret;
int bytes_read;
char buffer[CHUNKSIZE];
while (!feof(fd)) {
if ((bytes_read = fread(&buffer, 1, sizeof(buffer), fd)) > 0)
send(Connections[index], buffer, bytes_read, 0);
else
break;
}
fclose(fd);
Client:
char text[1024];
size_t datasize;
FILE* fd = fopen("download.txt", "wb");
while (true)
{
datasize = recv(Connection, (char*)&text, sizeof(text), NULL);
fwrite(&text, 1, datasize, fd);
}
fclose(fd);
But the client does not write anything to download.txt
What could be problem? (I am not pasting the full code because sending messages (recv, send) works well)

Related

TCP send a file data from client to server problem: different checksum on file

I try to transfer a data size of around 100MB over a TCP ipv4 connection socket.
I calculate the CheckSum in the client before sending it to see what the checksum is.
After sending the data file to the server and the server writes it to a new file I calculate again the checksum and I can see a differents.
I think is probably with my send and receive functions.
The Sender function used in CLIENT :
void send_file(FILE *fp, int sockfd) {
int n;
char data[SIZE] = {0};
while (fgets(data, SIZE, fp) != NULL) {
if (send(sockfd, data, sizeof(data), 0) == -1) {
perror("[-]Error in sending file.");
exit(1);
}
bzero(data, SIZE);
}
}
The Writer function the use in the SERVER:
void write_file(int sockfd, char *filename) {
int n;
FILE *fp;
//char *filename = "new_data.txt";
char buffer[SIZE];
fp = fopen(filename, "w");
while (1) {
n = recv(sockfd, buffer, SIZE, 0);
if (n <= 0) {
break;
return;
}
fprintf(fp, "%s", buffer);
bzero(buffer, SIZE);
}
}
fgets() and fprintf() are used for reading and writing zero-terminated strings, not arbitrary binary data. fread() and fwrite() are your friends here. Something like:
Client:
#define CHUNK_SIZE 1024
char buffer[CHUNK_SIZE];
while ((num_bytes = fread(buffer, 1, CHUNK_SIZE, fp)) > 0)
{
send(sockfd, buffer, num_bytes, 0);
}
Server:
// Same chunk size and buffer as above
while ((num_bytes = recv(sock, buffer, CHUNK_SIZE, 0)) > 0)
{
fwrite(buffer, 1, num_bytes, fp);
}
Technically fwrite() and send() can write less bytes than you ask them to, and you really should loop until all bytes are written.
You should also technically open your files with modes "rb" and "wb" for binary files.

Sending file from client to server goes wrong

I try to send a .jpeg file from client to server. Everytime I read a byte in my client I immediatley send it to my server and write it to the file. The file creation goes successfully but when I open the new image it doesn't view it. How can I send a file successfully?
server:
char buf[BUFSIZ]; // Array where the read objects are stored
FILE* copyFile; // Write to this
fopen_s(&copyFile, "C:\\Users\\name\\Documents\\img3.jpeg", "wb");
while (1)
{
recv(s, buf, BUFSIZ, 0);
fwrite(buf, 1, BUFSIZ, copyFile);
}
fclose(copyFile);
client:
char buf[BUFSIZ]; // Array where the read objects are stored
size_t size = BUFSIZ;
FILE* originalFile; // Read from this
fopen_s(&originalFile, "C:\\Users\\name\\Documents\\img.jpeg", "rb");
while (size == BUFSIZ)
{
size = fread(buf, 1, BUFSIZ, originalFile);
send(ClientSocket, buf, 1, 0);
}
fclose(originalFile);
You are ignoring the return values of both fread()/fwrite() and send()/recv(). They tell you how many bytes were actually read/written and sent/received, respectively. Never ignore the return values of system calls.
Try this instead:
server:
FILE* copyFile; // Write to this
if (fopen_s(&copyFile, "C:\\Users\\name\\Documents\\img3.jpeg", "wb") == 0)
{
char buf[BUFSIZ]; // Array where the read objects are stored
int numRecvd;
while ((numRecvd = recv(s, buf, sizeof(buf), 0)) > 0)
{
if (fwrite(buf, numRecvd, 1, copyFile) != 1) break;
}
fclose(copyFile);
}
client:
FILE* originalFile; // Read from this
if (fopen_s(&originalFile, "C:\\Users\\name\\Documents\\img.jpeg", "rb") == 0)
{
char buf[BUFSIZ]; // Array where the read objects are stored
size_t size;
while ((size = fread(buf, 1, sizeof(buf), originalFile)) > 0)
{
char *ptr = buf;
do {
int numSent = send(ClientSocket, ptr, size, 0);
if (numSent < 0) break;
ptr += numSent;
size -= numSent;
}
while (size > 0);
if (size != 0) break;
}
fclose(originalFile);
}

C/C++ Downloading / Uploading Files via socket

I am currently trying to work out Downloading / Uploading Files via socket (SOCK_STREAM). The following two functions are what I use to send and receive the data.
I am currently running into the following Issue(s):
The result File sometimes is not the same size as the source File
This Problem is more sever, the larger the file.
I am pretty sure that I am missing something obvious, in my loops maybe or determining the end of the data stream. I spent the past week trying a bunch of different approaches / solutions and this is the closest to a working version i got...
I am thankfull for any advice and review, if i need to provide further information please tell me
Function Sending Data from Server to Client:
void send_file(char *filename, int sock)
{
char data[1024] = {0};
FILE *fp = fopen(filename, "rb");
while (fread(data, sizeof(char), sizeof(data), fp) == 1024) {
if (send(sock, data, sizeof(data), 0) == -1) {
printf("%s%s[-] Error Transmitting File\n\n", KRED, BGHT);
break;
}
bzero(data, sizeof(data));
}
bzero(data, sizeof(data));
strcpy(data, "!EOF!");
send(sock, data, sizeof(data), 0);
bzero(data, sizeof(data));
printf("%s%s[+] Upload Successful\n\n", KGRN, BGHT);
fclose(fp);
}
Function of Client Receiving Data from Server:
void write_file(int sock, char *filepath)
{
FILE *fp;
int n;
char *lastSlash = strrchr(filepath, '\\');
char *filename = lastSlash ? lastSlash +1 : filepath;
char data[1024] = {0};
fp = fopen(filename, "wb");
while (1) {
n = recv(sock, data, sizeof(data), 0);
if (strncmp("!EOF!", data, 5) == 0) {
break;
}
if (n <= 0) {
break;
return;
}
fwrite(data, sizeof(char), sizeof(data), fp);
bzero(data, sizeof(data));
}
fclose(fp);
return;
}
i finally figured it out with the help of the following Post:
Sending files over TCP sockets C++ | Windows
I rewrote the example code to fit my needs. Works like a charm so far.
Thanks to all for giving me some more insight on the topic and helping me figure our the necessary checks on the way!
Here the new Code with a brief explanation:
First thing that needs to be recognized, ist that functions like send() recv() fread() fwrite() are likely to not fill their buffer entirely before passing it on. Meaning if you have a buffer specified with size 100, they might only fill it up to 89 95 or whatever. As a result files are likely to be corrupted. To solve this every call of the send() recv() fread() fwrite() functions needs to be checked.
First you need those two functions both on server and client side. These make sure the entire buffer is being sent / received.
Its basically just looping over send() / recv() until the buffer is filled up.
int RecvBuffer(int sock, char* buffer, int bufferSize, int chunkSize) {
int i = 0;
while (i < bufferSize) {
const int l = recv(sock, &buffer[i], __min(chunkSize, bufferSize - i), 0);
if (l < 0) { return l; }
i += l;
}
return i;
}
int SendBuffer(int sock, char* buffer, int bufferSize, int chunkSize) {
int i = 0;
while (i < bufferSize) {
const int l = send(sock, &buffer[i], __min(chunkSize, bufferSize - i), 0);
if (l < 0) { return l; }
i += l;
}
return i;
}
Next we need to apply the same check in the functions that are being called to Download / Upload a file. Here I loop over the above functions that fill our Buffer and over the fread() fwrite() until all bytes (fileSize) have been sent. The chunkSize parameter defines the size of each package being sent. I used 65.536 (64kb) so far without any issues.
int RecvFile(int sock, char *filePath, int chunkSize, int fileSize) {
char *lastSlash = strrchr(filePath, '\\');
char *filename = lastSlash ? lastSlash +1 : filePath;
FILE *fp = fopen(filename, "wb");
char buffer[chunkSize];
int i = fileSize;
while (i != 0) {
const int r = RecvBuffer(sock, buffer, (int)__min(i, (int)chunkSize), chunkSize);
if ((r < 0) || !fwrite(buffer, sizeof(char), r, fp)) { break; }
i -= r;
}
bzero(buffer, sizeof(buffer));
fclose(fp);
printf("\n%s%s[+] Download Successful\n\n", KGRN, BGHT);
return -3;
}
int SendFile(int sock, char *fileName, int chunkSize, int fileSize) {
FILE *fp = fopen(fileName, "rb");
char buffer[chunkSize];
int i = fileSize;
while (i != 0) {
const int ssize = __min(i, (int)chunkSize);
if (!fread(buffer, sizeof(char), ssize, fp)) { break; }
const int l = SendBuffer(sock, buffer, (int)ssize, (int)chunkSize);
if (l < 0) { break; }
i -= l;
}
bzero(buffer, sizeof(buffer));
fclose(fp);
printf("\n%s%s[+] Upload Successful\n\n", KGRN, BGHT);
return -3;
}

Sending and receiving file size successfully in C

I want to be able to send a file from the client to the server. I'm using TCP. I'm trying to use fseek and etc to get the size of the file because I want to be able to handle large files, and then send that amount of bytes of data as well as the files contents to the server. So far, according to my printf messages everything goes through and the file is created. However, the file created on the server is empty. There's obviously something wrong with the way I am sending it and receiving it via parameters or something, but I can't figure it out. Can someone please show me where I've gone wrong and how I can fix it because I'm so close!
Server part:
if(getFile){
char *tmp = buf + 9;
char filename2[MAX_BLOCK_SIZE];
int length, x;
long file_size = 0;
FILE *fp;
strcpy(filename2, tmp);
printf("Server receiving file name...\n");
//first 'read' receives the file name
fp = fopen(filename2, "wb");
if(fp == NULL){
printf("File could not be opened.\n");
exit(1);
}
printf("Server receiving file...\n");
while((x = read(sd, buf, sizeof(buf)) > 0)){ //second read now retrieving the file
printf("Server creating new file...\n");
fwrite(buf, 1, file_size, fp);
}
fclose(fp);
printf("The server has received the requested document.\n");
}
Client side:
else if(putCommand){
char *tmp = buf + 4;
char filename[MAX_BLOCK_SIZE];
long file_size;
strcpy(filename, "filename ");
strcat(filename, tmp);
FILE *fp;
printf("File name: %s\n", tmp);
fp = fopen(tmp, "rb");
if(fp == NULL){
printf("ERROR: Requested file does not exist.\n");
}
else{
printf("Client sending filename...\n");
if ((nw = write(sd, filename, sizeof(filename)) < nr)){ //sending the file name to the client first
printf("Error sending client's filename.\n");
}
//size_t file_size;
printf("Client sending file...\n");
fseek(fp, 0, SEEK_END);
long filesize = ftell(fp);
fseek(fp, 0, SEEK_SET);
while((file_size = fread(buf, 1, MAX_BLOCK_SIZE, fp)) > 0){ //sending the file
if ((x = write(sd, buf, filesize) < 0)){
printf("Error sending client file.\n");
}
}
fclose(fp);
}
It is close to a typo. On the receiver side, you have:
long file_size = 0;
...
while(...)
...
fwrite(buf, 1, file_size, fp);
So you consistently write 0 byte.
The standard way is:
while((x = read(sd, buf, sizeof(buf)) > 0)){ //second read now retrieving the file
printf("Server creating new file...\n");
fwrite(buf, 1, x, fp); // write the number of bytes returned by previous read
}
Last remark, I hope that buf is a true array and not a pointer...

Reading binary file in C (in chunks)

I'm not good at C and I'm trying to do something simple. I want to open a binary file, read blocks of 1024 bytes of data and dump into a buffer, process the buffer, read another 1024 byes of data and keep doing this until EOF. I know how / what I want to do with the buffer, but it's the loop part and file I/O I keep getting stuck on.
PSEUDO code:
FILE *file;
unsigned char * buffer[1024];
fopen(myfile, "rb");
while (!EOF)
{
fread(buffer, 1024);
//do my processing with buffer;
//read next 1024 bytes in file, etc.... until end
}
fread() returns the number of bytes read. You can loop until that's 0.
FILE *file = NULL;
unsigned char buffer[1024]; // array of bytes, not pointers-to-bytes
size_t bytesRead = 0;
file = fopen(myfile, "rb");
if (file != NULL)
{
// read up to sizeof(buffer) bytes
while ((bytesRead = fread(buffer, 1, sizeof(buffer), file)) > 0)
{
// process bytesRead worth of data in buffer
}
}
#include <stdio.h>
#include <unistd.h> // For system calls write, read e close
#include <fcntl.h>
#define BUFFER_SIZE 1024
int main(int argc, char* argv[]) {
unsigned char buffer[BUFFER_SIZE] = {0};
ssize_t byte = 0;
int fd = open("example.txt", O_RDONLY);
while ((byte = read(fd, buffer, sizeof(buffer))) != 0) {
printf("%s", buffer);
memset(buffer, 0, BUFFER_SIZE);
}
close(fd);
return 0;
}
Edited code added
#include <stdio.h>
#include <unistd.h> // For system calls write, read e close
#include <fcntl.h>
#define BUFFER_SIZE 1024
int main(int argc, char* argv[]) {
unsigned char buffer[BUFFER_SIZE] = {0};
ssize_t byte = 0;
// open file in read mode
int fd = open("example.txt", O_RDONLY);
// file opening failure
if (fd == -1) {
printf("Failed to open file\n");
return -1;
}
// loop
while (1) {
// read buffer
byte = read(fd, buffer, sizeof(buffer));
// error
if (byte == -1) {
printf("Encountered an error\n");
break;
} else if (byte == 0) {
// file end exit loop
printf("File reading end\n");
break;
}
// printf file data
printf("%s", buffer);
memset(buffer, 0, BUFFER_SIZE);
}
// Close file
close(fd);
return 0;
}

Resources