TFTP file transfer based on UDP (client code)
Code:
#include <my_head.h>
#define SERVER_PORT 69
#define SERVER_IP "192.168.125.91"
int do_download(int client_fd, struct sockaddr_in server_in);
int do_updata(int client_fd, struct sockaddr_in server_in);
int main(int argc, const char *argv[])
{<!-- -->
//Create a report socket
int client_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (client_fd < 0)
{<!-- -->
ERR_MSG("socket");
return -1;
}
printf("Socket created successfully client_fd = %d\
", client_fd);
//Allow ports to be reused quickly
int reuse = 1;
if (setsockopt(client_fd, SOL_SOCKET, SO_REUSEADDR, & amp;reuse, sizeof(reuse)) < 0)
{<!-- -->
ERR_MSG("setsockopt");
return -1;
}
printf("Allow port fast reuse successfully\
");
// Bind client information. Binding is not required. It is recommended not to bind.
// If not bound, the operating system will automatically assign a port number
//Specify server information
struct sockaddr_in server_addr; // Information used to bind this host
server_addr.sin_family = AF_INET; // AF_INET is required
// Because the report socket was created earlier using IPv4
server_addr.sin_port = htons(SERVER_PORT); //Specify port number
server_addr.sin_addr.s_addr = inet_addr(SERVER_IP); // Bind local IP
char choose = 0;
while (1)
{<!-- -->
printf("-------------------Menu------------------\
");
printf("-----------------1. Download------------------\
");
printf("-----------------2. Upload------------------\
");
printf("-----------------3. Exit------------------\
");
printf("---------------------------------------------\
") ;
printf("Please enter: ");
choose = getchar();
while (getchar() != '\
')
;
switch (choose)
{<!-- -->
case '1':
// download
do_download(client_fd, server_addr);
break;
case '2':
// Upload
do_updata(client_fd, server_addr);
break;
case '3':
// quit
goto END;
break;
default:
printf("Wrong selection, please re-enter\
");
break;
}
}
END:
//Close socket
close(client_fd);
return 0;
}
int do_download(int client_fd, struct sockaddr_in server_in)
{<!-- -->
/*
*ACK*/
unsigned short ACK[2] = {<!-- -->0};
/*
* file name */
char name[32];
printf("Please enter the file name you want to download: ");
scanf("%s", name);
while (getchar() != 10)
;
/*
* Combine a download protocol package */
char buff[516];
// opcode
unsigned short *opcode = (unsigned short *)buff;
*opcode = htons(1);
// file name
char *p2 = (char *)(opcode + 1);
strcpy(p2, name);
// model
char *mode = p2 + strlen(p2) + 1;
strcpy(mode, "octet");
/*
* Calculate the actual length of the protocol packet */
size_t size = 2 + strlen(p2) + 1 + strlen(mode) + 1;
/*
* Send the download protocol package to the server */
if (sendto(client_fd, buff, size, 0, (struct sockaddr *) & amp;server_in, sizeof(server_in)) < 0)
{<!-- -->
ERR_MSG("sendto");
return -1;
}
printf("Download protocol sent successfully\
");
/*
* Send and receive data */
ssize_t res = 0;
socklen_t server_in_len = sizeof(server_in);
/*
* File to store data packets */
umask(0);
int fd_w = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0664);
while (1)
{<!-- -->
/*
* Receive data packet */
res = recvfrom(client_fd, buff, sizeof(buff), 0, (struct sockaddr *) & amp;server_in, & amp;server_in_len);
if (res < 0)
{<!-- -->
ERR_MSG("recvfrom");
return -1;
}
// store data packet
char *data = buff + 4;
if (write(fd_w, data, res - 4) < 0)
{<!-- -->
ERR_MSG("write");
return -1;
}
// Assemble the ACK packet
ACK[0] = htons(4);
ACK[1] = *(((unsigned short *)buff) + 1);
//Send ACK packet
if (sendto(client_fd, ACK, sizeof(ACK), 0, (struct sockaddr *) & amp;server_in, sizeof(server_in)) < 0)
{<!-- -->
ERR_MSG("sendto");
return -1;
}
// printf("ACK sent successfully\
");
// Determine whether the data is less than 512Byte. If it is less than 512Byte, end the reception.
if ((res - 4) < 512)
{<!-- -->
printf("Download completed\
");
break;
}
}
close(fd_w);
return 0;
}
int do_updata(int client_fd, struct sockaddr_in server_in)
{<!-- -->
struct sockaddr_in new_in;
// new_in.sin_family = AF_INET;
socklen_t new_in_len = sizeof(new_in);
socklen_t server_in_len = sizeof(server_in);
// block number
unsigned short block_num = 1;
// file name
char name[32];
printf("Please enter the file name you want to upload: ");
scanf("%s", name);
while (getchar() != 10)
;
/*
* open a file */
int fd_r = open(name, O_RDONLY);
/*
* Combine a download protocol package */
char buff[516];
// opcode
unsigned short *opcode = (unsigned short *)buff;
*opcode = htons(2);
// file name
char *p2 = (char *)(opcode + 1);
strcpy(p2, name);
// model
char *mode = p2 + strlen(p2) + 1;
strcpy(mode, "octet");
/*
* Calculate the actual length of the protocol packet */
size_t size = 2 + strlen(p2) + 1 + strlen(mode) + 1;
/*
* Send the upload protocol package to the server */
if (sendto(client_fd, buff, size, 0, (struct sockaddr *) & amp;server_in, sizeof(server_in)) < 0)
{<!-- -->
ERR_MSG("sendto");
return -1;
}
printf("Download protocol sent successfully\
");
/*
* Receive protocol response */
if (recvfrom(client_fd, buff, sizeof(buff), 0, (struct sockaddr *) & amp;new_in, & amp;new_in_len) < 0)
{<!-- -->
ERR_MSG("recvfrom");
return -1;
}
printf("Protocol response operation code: %u\
", ntohs(*((unsigned short *)buff)));
printf("Protocol response block number: %u\
", ntohs(*((unsigned short *)buff + 1)));
//Send data and receive ACK
ssize_t res = -1; // Return value of reading file
ssize_t recv_res = 0; //Return value of receiving ACK
/*
*ACK*/
// unsigned int ACK = 0;
while (1)
{<!-- -->
bzero(buff, sizeof(buff));
/*
* Group data packet */
// opcode
unsigned short *opcode = (unsigned short *)buff;
*opcode = htons(3);
// block number
unsigned short *b_num = opcode + 1;
*b_num = htons(block_num);
/*
* data */
// read file
res = read(fd_r, buff + 4, 512);
if (res < 0)
{<!-- -->
ERR_MSG("read");
return -1;
}
else if (0 == res)
{<!-- -->
printf("Reading file completed\
");
}
printf("sizeof(buff) = %ld\
", sizeof(buff));
server_in_len = sizeof(server_in);
//Send packet
if (sendto(client_fd, buff, sizeof(buff), 0, (struct sockaddr *) & amp;new_in, new_in_len) < 0)
{<!-- -->
ERR_MSG("sendto");
return -1;
}
printf("Send data packet\
");
/*
* Receive response ACK */
recv_res = recvfrom(client_fd, buff, sizeof(buff), 0, (struct sockaddr *) & amp;new_in, & amp;new_in_len);
if (recv_res < 0)
{<!-- -->
ERR_MSG("recvfrom");
return -1;
}
printf("Operation code ---: %u\
", ntohs(*((unsigned short *)buff)));
printf("Block number ---: %u\
", ntohs(*((unsigned short *)buff + 1)));
if (5 == ntohs(*((unsigned short *)buff)))
{<!-- -->
printf("__%d__ ACK opcode error\
", __LINE__);
printf("errro message : %s\
", buff + 4);
return -1;
}
// Determine whether the packet is lost ---- Determine whether the previous data packet needs to be resent.
if (block_num - (ntohs(*((unsigned short *)buff + 1))))
{<!-- -->
printf("__%d__ packet loss\
", __LINE__);
lseek(fd_r, -(block_num - ntohs(*((unsigned short *)buff + 1))), SEEK_CUR);
printf("Offset forward\
");
continue;
}
if (0 == res)
{<!-- -->
printf("Upload completed\
");
break;
}
block_num + + ;
printf("Block number------%u\
", block_num);
}
close(fd_r);
return 0;
}