写了一个tftp客户端的下载, udp协议
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#define ERR_MSG(msg) do{\
perror(msg);\
return -1;\
}while(0)
#define SUC_MSG(msg) do{\
printf("%s success\n",msg);\
}while(0)
#define PORT 2305
#define IP "192.168.10.104"
#define SER_PORT 69
#define SER_IP "192.168.10.123"
int main(int argc, const char *argv[])
{
int sfd = socket(AF_INET,SOCK_DGRAM,0);
if(sfd < 0){
ERR_MSG("socket");
}
SUC_MSG("socket");
//quick reuse of PORT
int reuse = 1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) < 0){
ERR_MSG("setsockopt");
}
struct sockaddr_in cin;
cin.sin_family = AF_INET;
cin.sin_port = htons(PORT);
cin.sin_addr.s_addr = inet_addr(IP);
if(bind(sfd,(struct sockaddr*)&cin,sizeof(cin)) < 0){
ERR_MSG("bind");
}
SUC_MSG("bind");
//buf to restore all the packages
char buf[516] = "";
//a file name where you can read/write to
char filename[32] = "";
//a integer to restore how many bytes read/write during communication
int res = 0;
//a sockaddr_in to restore the temporary port
struct sockaddr_in sin;
int len = sizeof(sin);
//the size of the request string
int req_size = 0;
//choice of download or upload
int choice = 0;
sin.sin_family = AF_INET;
sin.sin_port = htons(SER_PORT);
sin.sin_addr.s_addr = inet_addr(SER_IP);
//read request
bzero(buf,sizeof(buf));
bzero(filename,sizeof(filename));
while(1){
printf("enter 1 to download or 2 to upload:\n");
scanf("%d",&choice);
getchar();
if(choice == 1 || choice == 2){
break;
}
}
//download
if(choice == 1){
*(short*)buf = htons(choice);
printf("Please enter the file name you want to download:\n");
fgets(filename,sizeof(filename),stdin);
filename[strlen(filename) - 1] = 0;
strcpy(buf + sizeof(short),filename);
strcpy(buf + sizeof(short) + strlen(filename) + 1, "octet");
req_size = sizeof(short) + strlen(filename) + 1 + strlen("octet") + 1;
res = sendto(sfd,buf,req_size,0,(struct sockaddr*)&sin,sizeof(sin));
if(res < 0){
ERR_MSG("request");
}
//if successfully requested for download,open a new file to save
printf("Please enter a file name you want to save:\n");
bzero(filename,sizeof(filename));
fgets(filename,sizeof(filename),stdin);
filename[strlen(filename) - 1] = 0;
int fd = open(filename,O_CREAT|O_TRUNC|O_WRONLY,0664);
if(fd < 0){
ERR_MSG("open");
}
//package number
int pac_num;
//error number
int err_num;
while(1){
bzero(buf,sizeof(buf));
res = recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,&len);
//if it's the last segment of the data
if(res < 516){
res = write(fd,buf + 2 * sizeof(short),res - 2*sizeof(short));
printf("download finished\n");
break;
}else if(res < 0){
ERR_MSG("recv");
}
//when no error happens,write in the data
if(ntohs(*(short*)buf) == 3){
pac_num = ntohs(*(short *)(buf + sizeof(short)));
res = write(fd,buf + 2 * sizeof(short),sizeof(buf) - 2 *sizeof(short));
bzero(buf,sizeof(buf));
*(short*)buf = htons(4);
*(short*)(buf + sizeof(short)) = htons(pac_num);
//send back the ACK to the server
res = sendto(sfd,buf,2*sizeof(short),0,(struct sockaddr*)&sin,len);
if(res < 0){
ERR_MSG("sendto");
}
//when error occurs,print out the error number and error message
}else if(ntohs(*(short*)buf) == 5){
err_num = ntohs(*(short *)(buf + sizeof(short)));
printf("err number is %d, %s\n",err_num,buf + 2 * sizeof(short));
break;
}
printf("[%s:%d] package%03d received\n",inet_ntoa(sin.sin_addr),ntohs(sin.sin_port),pac_num);
}
if(close(fd) < 0){
ERR_MSG("close");
}
}
//close all the file descriptors
if((close(sfd))< 0){
ERR_MSG("close");
}
return 0;
}