问题
Server Side Code.........
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#define BUFLEN 503
#define PORT 8885
void die(char *s)
{
perror(s);
exit(1);
}
int main(void)
{
struct sockaddr_in si_me, si_other;
int s, i,j, slen = sizeof(si_other) , recv_len;
char buf[BUFLEN];
if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
{
die("socket");
}
memset((char *) &si_me, '1', sizeof(si_me));
//printf("%d",si_me);
si_me.sin_family = AF_INET;
si_me.sin_port = PORT;
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
if( bind(s , (struct sockaddr*)&si_me, sizeof(si_me) ) == -1)
{
die("bind");
}
//memset(buf,0,503);
char fname[20];
FILE *fp;
recv_len = recvfrom(s, buf, 20, 0, (struct sockaddr *) &si_other, &slen);
char fna[100];
memset(buf,0,503);
recv_len = recvfrom(s, buf, 20, 0, (struct sockaddr *) &si_other, &slen);
strcpy(fna,buf);
//printf("%c\n",fna);
int len= strlen(fna);
printf("%d",len);
unsigned long mm = atoi(buf);
//printf("mm value: %ld\n",mm);
fp=fopen(fna,"wb");
int itr=1;
memset(buf,0,503);
while(itr*503<mm)
{
if ((recv_len = recvfrom(s, buf, 503, 0, (struct sockaddr *)&si_other, &slen)) == -1)
{
die("recvfrom()");
}
fwrite(buf,503, 1, fp);
memset(buf,0,503);
//printf("Loop no: %d",i)
//for(i=0;i<=itr;i++);
itr++;
}
//printf("Loop no: %d\n",i);
printf("%d",(mm%503));
recv_len = recvfrom(s, buf, (mm%503), 0, (struct sockaddr *) &si_other, &slen);
fwrite(buf,(mm%503), 1, fp);
memset(buf,0,503);
fclose(fp);
close(s);
return 0;
}
Client Side Code........
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#define SERVER "127.0.0.1"
#define BUFLEN 503
#define PORT 8885
void die(char *s)
{
perror(s);
exit(1);
}
unsigned long fsize(char* file)
{
//String bbb=file;
FILE * f = fopen(file, "r");
fseek(f, 0, SEEK_END);
unsigned long len = (unsigned long)ftell(f);
printf("Total size: %d \n",len);
fclose(f);
return len;
}
int main(void)
{
struct sockaddr_in si_other;
int s, i, slen=sizeof(si_other);
char buf[BUFLEN];
char message[BUFLEN];
if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
{
die("socket");
}
memset((char *) &si_other, '1', sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = PORT;
//printf("Htons= %d \n",htons(PORT));
if (inet_aton(SERVER , &si_other.sin_addr) == 0)
{
fprintf(stderr, "inet_aton() failed\n");
exit(1);
}
//memset(message,0,503);
char fname[20];
printf("Enter Filename with extension: ");
scanf("%s",&fname);
sendto(s, fname, 20 , 0 , (struct sockaddr *) &si_other, slen);
memset(message,0,503);
unsigned long siz = fsize(fname);
printf("siz: %ld\n",siz);
char str[10];
sprintf(str, "%d", siz);
int send1=sendto(s, str, 20 , 0 , (struct sockaddr *) &si_other, slen);
printf("value of send1= %d",send1);
FILE *f;
f=fopen(fname,"rb");
memset(message,0,503);
fread(message, 503,1,f);
int itr =1;
while(itr*503<siz){
if (sendto(s, message, 503 , 0 , (struct sockaddr *) &si_other, slen)==-1)
{
die("sendto()");
}
memset(message,0,503);
fread(message, 503,1,f);
itr++;
}
fread(message, (siz % 503),1,f);
int send2=sendto(s, message, (siz % 503) , 0 , (struct sockaddr *) &si_other, slen);
printf("\n value of send 2= %d",send2);
memset(message,0,503);
fclose(f);
close(s);
return 0;
}
This is the code for file transfer like images, videos, text files in UDP socket programming.(From Client Side To Server Side folder).
Can anyone explain to me why the WHILE
loop is being used on both the sides, What is its purpose?
Also, one problem is using this program the file is sent properly from client to server but after reaching the server side the filename is being changed.
unsigned long len = (unsigned long)ftell(f);
printf("Total size: %d \n",len);
After testing I found out that the changed file name on the server side is set to the current position of the file pointer that is in len
variable in client side.(value of len
is same as variable mm
in server side and variable 'siz
' on client side.
for example:
If I send "Wallpaper.png" from server side it will reach the server side and the file is saved by the name "164101". But the image is displayed properly.
AND WHY IS memset USED SO MANY TIMES ?? WHAT IS ITS ACTUAL USE ??
回答1:
Your client and server speak the same file transfer protocol, defined as follows :
- first 20 bytes contain the file name
- 20 bytes contain the file length
- actual bytes are sent and received by chunks of 503 bytes
- final chunk (lower than 503 bytes) is fetched at the end
On the server side, you're messing with variables that should store the file name fname
and the one that should store the file length fna
. You should probably rename the latter to flen
like in the following snippet :
...
char fname[20]; // variable to store file name
FILE *fp;
recv_len = recvfrom(s, buf, 20, 0, (struct sockaddr *) &si_other, &slen);
strcpy(fname, buf); // got 20 bytes in buf, copy to fname : this is the file name
printf("File name : %s\n", fname);
char flen[20];
memset(buf,0,503); // reset NULL bytes to buf
recv_len = recvfrom(s, buf, 20, 0, (struct sockaddr *) &si_other, &slen);
strcpy(flen, buf); // got 20 bytes, copy to flen : this is the file length (as a string)
printf("Length as string : %s\n", flen);
printf("Length as integer : %d\n", atoi(flen));
unsigned long mm = atoi(buf); // convert file length as a string to an integer variable
printf("mm value: %ld\n",mm);
fp=fopen(fname,"wb"); // use the proper variable as the file name
int itr=1;
...
Hope this helps!
回答2:
The while
loop is used to split the file into smaller chunks which fit into UDP datagrams, which have a limited size. Unlike TCP, UDP does not deal with such details, so you have to implement all of that on your own.
Eventually, you will also have to implement timeouts and retransmits, duplicate datagram detection, and probably some form of congestion control. Writing a good file transport protocol which beats a TCP-based solution on top of UDP is quite hard.
来源:https://stackoverflow.com/questions/47031592/udp-socket-programming-file-transfer