I am trying to send a file from client to server. It sometime worksand sometime don't. when first time trying to send file, it sends corrupt file and the file side formed at server side is double of its size. But file successful transfers for all attempts after first attempt. Can anyone help me with this ?
Client.c
message msg;
msg.type = SEND_FILE;
char *username, *filename;
username = strtok(input+6, " ");
filename = strtok(NULL, "");
//Get Picture Size
printf("Getting Picture Size\n");
FILE *picture;
picture = fopen(filename, "r");
int size;
fseek(picture, 0, SEEK_END);
size = ftell(picture);
fseek(picture, 0, SEEK_SET);
//Send Picture Size
printf("Getting Picture Size\n");
sprintf(msg.data, "%d", size);
strncpy(msg.username, username, 20);
if(send(connection->socket, &msg, sizeof(message), 0) < 0)
{
perror("Send failed");
exit(1);
}
//Send Picture as Byte Array
printf("Sending Picture as Byte Array\n");
char send_buffer[size+1];
fread(send_buffer, 1, sizeof(send_buffer), picture);
write(connection->socket, send_buffer, sizeof(send_buffer));
bzero(send_buffer, sizeof(send_buffer));
server.c
//Read Picture Size
printf("Reading Picture Size\n");
int size = atoi(message_text);
//Read Picture Byte Array
printf("Reading Picture Byte Array\n");
char p_array[size];
printf("Converting Byte Array to Picture %d\n", size);
FILE *image;
image = fopen("c4.png", "w");
int readSize = 0;
while (readSize < size) {
readSize = readSize + read(clients[sender].socket, p_array, size);
fwrite(p_array, 1, sizeof(p_array), image);
}
fclose(image);
For starters:
You don't want to store the same number of bytes on every fwrite()
fwrite(p_array, 1, sizeof(p_array), image);
but only the number of bytes actually read.
sizeof(p_array) returns the size of p_array, which is size times the size of a char. The latter is defined as being 1.
Besides this the call to read() completely lacks error checking, along with the test whether the other side shut down the connection. This is not leading far.
To fix this you could do:
#include <errno.h> /* for errno */
...
size_t size = atoi(message_text);
printf("Reading Picture Byte Array\n");
char p_array[size];
size_t readSize = 0;
while (readSize < size) {
ssize_t result = read(clients[sender].socket, p_array, size); /* Mind the ssize_t, it's *not* size_t! */
if (0 >= result)
{
if (0 == result)
{
fprintf(stderr, "The other end gracefully shut down the connection.\n");
break;
}
else
{
if (EINTR == errno) /* got interrupted, start over */
{
continue;
}
if (EAGAIN == errno) /* in case reading from a non-blocking socket: no data available, start over */
{
continue;
}
/* Something went wrong unrecoverable. */
perror("read() failed");
break;
}
}
else
{
fwrite(p_array, 1, result, image);
/* Also add error checking here! */
readSize += result;
}
}
Related
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.
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(©File, "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(©File, "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);
}
In here I am sending file name first then sending the file in chunks, then trying to read the received message but it is just freezing. No respond. But after loop if I shutdown the WR shutdown(connfd,SHUT_WR); It is working fine. Though I should be able to send message again, if I do this I can not do that.
CLIENT.C
write(sockfd, fname,100);
FILE *fp = fopen(fname,"rb");
if(fp==NULL)
{
printf("File opern error");
exit(1);
}
int hi = 0;
while(1)
{
/* First read file in chunks of 256 bytes */
unsigned char buff[1024]={0};
int nread = fread(buff,1,1024,fp);
/* If read was success, send data. */
if(nread > 0)
{
hi++;
//printf("Sending \n");
write(sockfd, buff, nread);
}
if (nread < 1024)
{
if (feof(fp))
{
printf("File transfer completed!\n");
}
if (ferror(fp))
printf("Error reading\n");
break;
}
}
char fname2[100];
// cant read
read(sockfd, fname2, 100);
printf("File Name: %s\n",fname2);
SERVER.C
FILE *fp;
int bytesReceived = 0;
char recvBuff[1024];
char fname[100];
char fname2[100];
read(newsockfd, fname, 100);
//strcat(fname,"AK");
printf("File Name: %s\n",fname);
printf("Receiving file...");
fp = fopen(fname, "ab");
if(NULL == fp)
{
printf("Error opening file");
}
long double sz=1;
/* Receive data in chunks of 256 bytes */
printf("\nCompleted.\n");
int hi = 0;
while((bytesReceived = read(newsockfd, recvBuff, 1024)) > 0)
{
hi++;
sz++;
fwrite(recvBuff, 1,bytesReceived,fp);
}
printf("Not pring this this!");
if(bytesReceived < 0)
{
printf("\n Read Error \n");
}
write(newsockfd, "SayGee",100);
I had to send the size of the file, then check from the other side inside loop. It was in deadlock.I found the solution. So thanks anyway!
I have written the following code for sending file from a client:
FILE *fp = fopen("video.mp4","rb");
if(fp==NULL)
{
printf("File opern error");
return 1;
}
int bytesToWrite=84440670;
int bytesWritten=0;
while(bytesWritten<bytesToWrite)
{
int m=minimum(256,bytesToWrite-bytesWritten);
/* First read file in chunks of 256 bytes or the remaining bytes*/
unsigned char *buff=malloc(sizeof(char)*m);
bzero(buff, m);
int nread = fread(buff,1,m,fp);
printf("Bytes read %d \n", nread);
bytesWritten+=m;
/* If read was success, send data. */
if(nread > 0)
{
printf("Sending \n");
write(sockfd, buff, nread);
}
/*
* There is something tricky going on with read ..
* Either there was error, or we reached end of file.
*/
if (nread < 256)
{
if (feof(fp))
printf("End of file\n");
if (ferror(fp))
printf("Error reading\n");
break;
}
}
and the following code for receiving by the server :
FILE *fp;
fp = fopen("receive.mp4", "wb");
if(NULL == fp)
{
printf("Error opening file");
return 1;
}
int bytesToRead=84440670;
/* Receive data in chunks of 256 or remaining bytes */
int totalbytesread=0;
while(totalbytesread < bytesToRead)
{
int m = minimum(256,bytesToRead-totalbytesread);
char *recvBuff=malloc(sizeof(char)*m);
bzero(recvBuff,m);
bytesReceived = read(newsocfd, recvBuff,m );
printf("Bytes received %d\n",bytesReceived);
totalbytesread += bytesReceived;
fwrite(recvBuff, 1,bytesReceived,fp);
}
if(bytesReceived < 0)
{
printf("\n Read Error \n");
}
The sending is working correctly for .txt files ,some data is being lost in sending other formats(for e.g some ending seconds of .mp4 files is not being sent).
I am new to socket programming. Any help would be deeply appreciated.
You are missing a fclose(fp); in the server after you have finished receiving. You can also use fflush(fp); to just flush the contents.
Besides, there are several memory leaks and improper error handling.
I'm trying to send an image file through a TCP socket in C, but the image isn't being reassembled correctly on the server side. I was wondering if anyone can point out the mistake?
I know that the server is receiving the correct file size and it constructs a file of that size, but it isn't an image file.
Client
//Get Picture Size
printf("Getting Picture Size\n");
FILE *picture;
picture = fopen(argv[1], "r");
int size;
fseek(picture, 0, SEEK_END);
size = ftell(picture);
//Send Picture Size
printf("Sending Picture Size\n");
write(sock, &size, sizeof(size));
//Send Picture as Byte Array
printf("Sending Picture as Byte Array\n");
char send_buffer[size];
while(!feof(picture)) {
fread(send_buffer, 1, sizeof(send_buffer), picture);
write(sock, send_buffer, sizeof(send_buffer));
bzero(send_buffer, sizeof(send_buffer));
}
Server
//Read Picture Size
printf("Reading Picture Size\n");
int size;
read(new_sock, &size, sizeof(int));
//Read Picture Byte Array
printf("Reading Picture Byte Array\n");
char p_array[size];
read(new_sock, p_array, size);
//Convert it Back into Picture
printf("Converting Byte Array to Picture\n");
FILE *image;
image = fopen("c1.png", "w");
fwrite(p_array, 1, sizeof(p_array), image);
fclose(image);
Edit: Fixed sizeof(int) in server code.
you need to seek to the beginning of the file before you read
fseek(picture, 0, SEEK_END);
size = ftell(picture);
fseek(picture, 0, SEEK_SET);
or use fstat to get the file size.
Check fread and fwrite syntax:
size_t fread(void *ptr, size_t size, size_t n, FILE *fp);
size_t fwrite(const void *ptr, size_t size, size_t n, FILE *fp);
In your case correct statement should be:
fread(send_buffer, sizeof(send_buffer), 1, picture);
fwrite(p_array, sizeof(p_array), 1,image);
Although it's an old post, I must highlight a few problems in the original code :
feof(picture) is always false after fopen. You must always make a read before calling feof
read(new_sock, p_array, size) is not guaranteed to read size bytes, it depends on the value of size, network load, server load,...
A correct (at least more robust) version would be :
//Send Picture as Byte Array (without need of a buffer as large as the image file)
printf("Sending Picture as Byte Array\n");
char send_buffer[BUFSIZE]; // no link between BUFSIZE and the file size
int nb = fread(send_buffer, 1, sizeof(send_buffer), picture);
while(!feof(picture)) {
write(sock, send_buffer, nb);
nb = fread(send_buffer, 1, sizeof(send_buffer), picture);
// no need to bzero
}
Same problem on server side :
//Read Picture Byte Array
printf("Reading Picture Byte Array\n");
char p_array[size];
char* current = p_array;
int nb = read(new_sock, current, size);
while (nb >= 0) {
current = current + nb;
nb = read(new_sock, current, size);
}
On server side you can avoid the creation of a buffer as large a image file (which might be a problem with large images) :
//Read Picture Byte Array and Copy in file
printf("Reading Picture Byte Array\n");
char p_array[BUFSIZE];
FILE *image = fopen("c1.png", "w");
int nb = read(new_sock, p_array, BUFSIZE);
while (nb > 0) {
fwrite(p_array, 1, nb, image);
nb = read(new_sock, p_array, BUFSIZE);
}
fclose(image);