linux网络编程之断点传输文件
来源:互联网 发布:王者荣耀kda最新算法 编辑:程序博客网 时间:2024/06/05 13:23
以下载链接“http://www.boa.org/boa-0.94.13.tar.gz”为例:断点续传实验大概步骤:=====================1,使用gethostbyname()获取站点“www.boa.org”的IP地址2,以“boa-0.94.13.tar.gz”为例,构建HTTP请求报文首部: char *httpreq = "GET /boa-0.94.13.tar.gz HTTP/1.1\r\n" "Range: bytes=%d-%d\r\n" "Host: %s\r\n\r\n" begin, end, host);注意: A) 以上字符串httpreq就是发送给远程主机www.boa.org的HTTP请求报文,通过TCP发送 B) Range字段是要求主机发送申请文件的部分内容,begin和end分别是文件的开始和结束 B.1 如果写成 "Range: bytes=0-\r\n",代表要求主机发送全文 B.2 如果写成 "Range: bytes=-1000\r\n",代表要求主机发送前1000个字节 B.3 如果写成 "Range: bytes=0-200\r\n",代表要求主机发送前200个字节 C) 正常情况下,HTTP服务器会对这个请求报文返回206,并给出实际返回的字节数和范围: C.1 "Content-Length: 1000" 这个字段代表本次HTTP发来的数据大小为1000个字节(不含HTTP首部) C.2 "Content-Range: bytes 2000-2999/9999" 代表本次传送的数据范围是第2000-2999个字节(共1000个字节),而所请求的文件总大小是9999个字节。3,将收到的报文的HTTP首部去掉(HTTP首部是指从开头到\r\n\r\n结尾的部分),剩下的就是下载的文件内容4,将文件内容以非缓冲方式保存下来。5,如果发生下载时网络断线,或者人为终止了下载进程,那么在下一次下载时先获取当前已下载部分的大小,并作为Range参数告知远端HTTP服务器,要求发送部分文件,实现断点续传,节约网络流量节约时间。
#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/stat.h>#include <netdb.h>#include <arpa/inet.h>#include <netinet/in.h>#include <sys/socket.h>#include <string.h>#include <strings.h>#include <sys/types.h>#include <fcntl.h>#include <assert.h>#include <stdbool.h>#include "common.h"#define RWRWRW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)#define SERV_PORT 80#define FILENAME "boa-0.94.13.tar.gz"typedef struct sockaddr SA;void http_request(char *buf, int size, const char *filename , const int begin, const char *host);int main(void){ int sockfd; struct sockaddr_in servaddr; struct hostent *hptr = NULL; struct in_addr **pptr = NULL; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { err_quit("socket error"); } char *hostname = "www.boa.org"; if ((hptr = gethostbyname(hostname)) == NULL) { err_quit("gethostbyname error for host: %s: %s", hostname, hstrerror(h_errno)); } pptr = (struct in_addr**)hptr->h_addr_list; bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(SERV_PORT); memcpy(&servaddr.sin_addr, *pptr, sizeof(struct in_addr)); if (connect(sockfd, (SA *)&servaddr, sizeof(servaddr)) < 0) { err_quit("connect error"); } int fd; int file_size; struct stat statbuf; if (access(FILENAME, F_OK)) { if ((fd = open(FILENAME, O_WRONLY|O_CREAT, RWRWRW)) < 0) { err_sys("create %s failure", FILENAME); } file_size = 0; } else { if ((fd = open(FILENAME, O_APPEND|O_WRONLY, RWRWRW)) < 0) { err_sys("open %s failure", FILENAME); } if (stat(FILENAME, &statbuf) < 0) { err_sys("stat error"); } file_size = statbuf.st_size; }#ifdef DEBUG printf(" host:\t%s\n", hostname); printf(" filename:\t%s\n", FILENAME); printf("start size:\t%d\n", file_size); printf("------------------------------------------------\n\n");#endif char request[MAXLINE]; http_request(request, sizeof(request), FILENAME, file_size, hostname); if (write(sockfd, request, strlen(request)) != strlen(request)) { err_quit("request failure"); } char recvbuf[4096]; int nread; bool flage = true; char tar[] = "\r\n\r\n"; char *begin = NULL; while (1) { bzero(recvbuf, sizeof(recvbuf)); if ((nread = read(sockfd, recvbuf, sizeof(recvbuf))) <= 0) { if (0 == nread) { break; } else { err_sys("read error"); } } if (flage) { if ((begin = strstr(recvbuf, tar)) == NULL) { continue; } else { write(fd, begin+strlen(tar), nread-(begin-recvbuf)-strlen(tar)); flage = false; } } if (!flage) { if (write(fd, recvbuf, nread) != nread) { err_quit("write error"); } }#ifdef DEBUG printf("******"); fflush(stdout);#endif }/* if (stat(FILENAME, &statbuf) < 0) { err_quit("stat failure"); } else { if (statbuf.st_size == full_size) { printf("---success!---\n"); } }*/ printf("---success!---\n"); return EXIT_SUCCESS;}void http_request(char *buf, int size, const char *filename, const int begin, const char *host){ assert(buf); assert(filename); assert(host); bzero(buf, size); snprintf(buf, size, "GET /%s " "HTTP/1.1\r\n" "Range: bytes=%d-\r\n" "Host: %s\r\n\r\n", filename, begin, host);}
阅读全文
1 0
- linux网络编程之断点传输文件
- Linux网络编程之使用UDP传输文件
- Linux网络编程之使用TCP传输文件
- Linux网络编程之使用TCP传输文件
- Linux网络编程之使用TCP传输文件
- Linux网络编程之使用TCP传输文件
- Linux网络编程之使用UDP传输文件
- Linux网络编程之使用TCP传输文件
- linux网络传输文件
- linux下网络编程3:UDP广播传输文件
- Linux C——网络编程传输文件的实验
- linux网络编程-UDP实现文件的传输
- 网络编程之UDP传输
- 网络编程--多线程断点下载文件
- Android网络编程之——文件断点下载(暂停/继续/重新下载)
- [转帖]socket 网络编程 点对点传输文件
- VC++使用Socket网络编程传输文件
- 网络编程,一个ACSII文件的传输
- eclipse设置jdk源码
- 编程时常出现的问题
- python json (loads(),load(),jump(),jumps())
- 【倍增】 luogu 1613 跑路
- Unity 回合制战斗系统(高级篇)
- linux网络编程之断点传输文件
- Kotlin入门篇(一),基本数据类型介绍、变量和常量的声明
- Android UI
- CentOS7 matplotlib notebook 安装和使用
- JZOJsenior1444. 交换【推荐】
- 越大越聪明(输出路径问题)
- 用spark统计50年美国最常见的20个名字
- 【JAVA】数据库连接池(DBCP)的使用与操作
- codeforce-404D---Minesweeper 1D(dp)