tftp代码实现
#define SER_PORT 69 #define SER_IP "192.168.125.85" int sockfd; char buf[516]; struct sockaddr_in ser_sockaddr; void print_menu(); void upload(const char* filename); void download(const char* filename); int main(int argc, const char *argv[]) { char num; // 菜单选择号 char filename[30]; sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd == -1) { perror("socket"); return -1; } ser_sockaddr.sin_family = AF_INET; ser_sockaddr.sin_port = htons(SER_PORT); ser_sockaddr.sin_addr.s_addr = inet_addr(SER_IP); print_menu(); while (1) { printf("请选择->"); scanf(" %c", &num); switch (num) { case '1': printf("请输入上传文件名->"); scanf("%s", filename); upload(filename); break; case '2': printf("请输入下载文件名->"); scanf("%s", filename); download(filename); break; case '3': system("clear"); print_menu(); break; case '4': close(sockfd); return 0; default: puts("输入错误,请重新输入"); } } return 0; } void print_menu() { puts("**************************************"); puts("***************1 上传*****************"); puts("***************2 下载*****************"); puts("***************3 清屏*****************"); puts("***************4 退出*****************"); puts("**************************************"); } void upload(const char* filename) { // 发送写请求 short* op_ptr = (short*)buf; *op_ptr = htons(2); char* filename_ptr = buf + 2; strcpy(filename_ptr, filename); char* mode_ptr = filename_ptr + strlen(filename_ptr) + 1; strcpy(mode_ptr, "octet"); int req_len = 4 + strlen(filename_ptr) + strlen(mode_ptr); sendto(sockfd, buf, req_len, 0, (struct sockaddr*)&ser_sockaddr, sizeof(struct sockaddr)); socklen_t sockaddr_len = sizeof(struct sockaddr); recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&ser_sockaddr, &sockaddr_len); //收到操作码为5,代表上传发生错误 if (ntohs(*(short*)buf) == 5) { printf("%s\n", buf + 4); return; } int i = 1; // 块编号 int rfd = open(filename, O_RDONLY); if (rfd == -1) { perror("open"); return; } while (1) { *op_ptr = htons(3); short* blocknum_ptr = (short*)(buf + 2); *blocknum_ptr = htons(i++); int ret = read(rfd, buf + 4, 512); sendto(sockfd, buf, ret + 4, 0, (struct sockaddr*)&ser_sockaddr, sockaddr_len); // 等待服务器端ACK recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&ser_sockaddr, &sockaddr_len); if (ntohs(*(short*)buf) == 5) { printf("%s\n", buf + 4); close(rfd); return; } if (ret < 512) { puts("上传完成"); close(rfd); return; } } } void download(const char* filename) { // 发送读请求 short* op_ptr = (short*)buf; *op_ptr = htons(1); char* filename_ptr = buf + 2; strcpy(filename_ptr, filename); char* mode_ptr = filename_ptr + strlen(filename_ptr) + 1; strcpy(mode_ptr, "octet"); int req_len = 4 + strlen(filename_ptr) + strlen(mode_ptr); sendto(sockfd, buf, req_len, 0, (struct sockaddr*)&ser_sockaddr, sizeof(struct sockaddr)); int wfd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0666); if (wfd == -1) { perror("open"); return; } int i = 1; //块编号 socklen_t sockaddr_len = sizeof(struct sockaddr); while (1) { // 接收数据包 int ret = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&ser_sockaddr, &sockaddr_len); if (ret < 0) { perror("recvfrom"); close(wfd); return; } write(wfd, buf + 4, ret - 4); // 发送ACK *op_ptr = htons(4); short* blocknum_ptr = (short*)(buf + 2); *blocknum_ptr = htons(i++); sendto(sockfd, buf, 4, 0, (struct sockaddr*)&ser_sockaddr, sockaddr_len); if (ret < 516) { puts("下载完成"); close(wfd); return; } } }
还没有评论,来说两句吧...