Reputation: 602
The program is supposed to send the contents of a file from the client side to an output file on the server side. However, my code is working for few files and not working for most of the files. For example if I try to copy content of a file called morefood.txt
to an output file say picolo.txt
, nothing is copied.
Server code:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
int main(int argc, char *argv[]){
int fd =0, confd = 0;
struct sockaddr_in serv_addr;
char buff[1025];
int num;
fd = socket(AF_INET, SOCK_STREAM, 0);
printf("Socket created\n");
memset(&serv_addr, '0', sizeof(serv_addr));
memset(buff, '0', sizeof(buff));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(5000);
bind(fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
listen(fd, 10);
FILE* fp = fopen( "picolo.txt", "wb");
if(fp == NULL){
fprintf(stderr, "something went south");
return 1;
}
while(1){
confd = accept(fd, (struct sockaddr*)NULL, NULL);
char recvbuff[10];
int b = recv(confd, recvbuff, 10, 0);
while(b>0)
{
fwrite(recvbuff, 1, b, fp);
b = recv(confd, recvbuff, 10, 0);
}
close(confd);
}
return 0;
}
Client code:
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
int main(int argc, char *argv[]){
int sfd =0, n=0;
char rbuff[1024];
struct sockaddr_in serv_addr;
memset(rbuff, '0', sizeof(rbuff));
sfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(5000);
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
FILE *fp = fopen("morefood.txt", "rb");
if(fp == NULL){
fprintf(stderr, "oh no!");
return 1;
}
char sendbuffer[100];
int b = fread(sendbuffer, 1, sizeof(sendbuffer), fp);
while(!feof(fp)){
send(sfd, sendbuffer, b, 0);
b = fread(sendbuffer, sizeof(sendbuffer), 1, fp);
}
return 0;
}
Upvotes: 5
Views: 16545
Reputation: 348
Part to read from file in server
.
. // Your other code
.
read(client, rbuff, sizeof(rbuff); //Getting file name from client
printf("File wanted by client%s\n", textToRec);
int filedesc = open(textToRec, O_RDONLY); //Opening the file
struct stat sb; //To get the size of file
if (lstat(ruff, &sb) == -1) {
exit(EXIT_FAILURE);
}
long long fsize;
fsize = sb.st_size;
if ((0 == filedesc)) {
fprintf(stderr,"error in reading file");
exit(-1);
}
write(client, fsize, sizeof(fsize)); //Sending Filesize
read(filedesc, sendbuffer, fsize); //Putting file in buffer
write(client, sendbuffer, sizeof(sendbuffer)); //Sending buffer to client
close(socketid);
.
.
. // Your code
Part on the client side:
/* your code above */
printf("file name sent...Now wait!\n");
// I am assuming you put filename in buff
read(sock, buff,sizeof(buff)); //Receiving file size
long long fsize = strtol(buff,NULL,10);
read(sock, buff,sizeof(buff));
/*It's better to use sizeof instead of actual number as you can change the size of buffer anytime without needing to change values everywhere */
int filedesc;
filedesc =
open(textToSend, O_WRONLY | O_APPEND | O_CREAT, 0644);
if (!filedesc) {
printf("failed to create file\n");
exit;
}
write(filedesc, buff, fsize);
close(filedesc);
close(confd);
Upvotes: 0
Reputation: 2096
The issue is that both transmission and reception loop are bugged! I've modified them in a way that the codes run better, but I think there's a lot to modify to have a solid code!
Client:
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
int main(int argc, char *argv[]){
int sfd =0, n=0, b;
char rbuff[1024];
char sendbuffer[100];
struct sockaddr_in serv_addr;
memset(rbuff, '0', sizeof(rbuff));
sfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(5000);
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
b=connect(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
if (b==-1) {
perror("Connect");
return 1;
}
FILE *fp = fopen("prova.jpg", "rb");
if(fp == NULL){
perror("File");
return 2;
}
while( (b = fread(sendbuffer, 1, sizeof(sendbuffer), fp))>0 ){
send(sfd, sendbuffer, b, 0);
}
fclose(fp);
return 0;
}
Server:
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
int main(int argc, char *argv[]){
int fd =0, confd = 0,b,tot;
struct sockaddr_in serv_addr;
char buff[1025];
int num;
fd = socket(AF_INET, SOCK_STREAM, 0);
printf("Socket created\n");
memset(&serv_addr, '0', sizeof(serv_addr));
memset(buff, '0', sizeof(buff));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(5000);
bind(fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
listen(fd, 10);
while(1){
confd = accept(fd, (struct sockaddr*)NULL, NULL);
if (confd==-1) {
perror("Accept");
continue;
}
FILE* fp = fopen( "provacopy.jpg", "wb");
tot=0;
if(fp != NULL){
while( (b = recv(confd, buff, 1024,0))> 0 ) {
tot+=b;
fwrite(buff, 1, b, fp);
}
printf("Received byte: %d\n",tot);
if (b<0)
perror("Receiving");
fclose(fp);
} else {
perror("File");
}
close(confd);
}
return 0;
}
Upvotes: 6
Reputation: 16550
this code, in the client:
char sendbuffer[100];
int b = fread(sendbuffer, 1, sizeof(sendbuffer), fp);
while(!feof(fp)){
send(sfd, sendbuffer, b, 0);
b = fread(sendbuffer, sizeof(sendbuffer), 1, fp);
}
is not a good way to send a 'nameless' file.
I suggest
while( 0< (byteCount = fread( sendbuffer, sizeof(sendbuffer), 1, fp) ) )
{
send(sfd, sendbuffer, byteCount, 0);
}
however, for robustness
--client send a file name and total file size with recordNum 0
--server when receiving recordNum 0
open the appropriate file name
if successful open, send 'ack', maxRecordSize echo recordNum
else send 'nak' echo recordNum
--client, on following records,
send byteCount, recordNum, data
--server respond with 'ack' for each received record
when it is expected recordNum
otherwise respond with 'nak' expected recordNum
--when client receives 'ack' send next record
--when client receives 'nak' resend prior record
--client, after all file sent, send file checksum with recordnum -1
--server, when receive recordNum -1 compares checksum, closes file
responds with final 'ack' if checksum matches
responds with final 'nak' if checksum does not match
This 'lockstep' communication, which is often used in the real world, will assure both ends of the communication know what is going on and will assure a successful file transfer,
This works for only one file being sent at a time. for multiple files being sent at the same time, the records will need another field, that indicates which file 'this' record is part of.
of course, all send/recv/open/connect/bind/ etc system function calls need to have the returned value(s) checked for errors
Upvotes: 2