以下载链接“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);
}

linux网络编程之断点传输文件的更多相关文章

  1. Android网络编程只局域网传输文件

    Android网络编程之局域网传输文件: 首先创建一个socket管理类,该类是传输文件的核心类,主要用来发送文件和接收文件 具体代码如下: package com.jiao.filesend; im ...

  2. Java 学习笔记 网络编程 使用Socket传输文件 CS模式

    Socket的简单认识 Socket是一种面向连接的通信协议,Socket应用程序是一种C/S(Client端/Server端)结构的应用程序 Socket是两台机器间通信的端点. Socket是连接 ...

  3. Linux网络编程系列-TCP传输控制

    滑动窗口(sliding window) 滑动窗口是用于流量控制的,发送端根据接收端的处理能力发送数据,不至于造成过多的丢包. 是发送方和接收方间的协调,对方的接收窗口大小就是自己的发送窗口大小. 在 ...

  4. linux网络编程-(socket套接字编程UDP传输)

    今天我们来介绍一下在linux网络环境下使用socket套接字实现两个进程下文件的上传,下载,和退出操作! 在socket套接字编程中,我们当然可以基于TCP的传输协议来进行传输,但是在文件的传输中, ...

  5. 【linux草鞋应用编程系列】_5_ Linux网络编程

    一.网络通信简介   第一部分内容,暂时没法描述,内容实在太多,待后续专门的系列文章.   二.linux网络通信     在linux中继承了Unix下“一切皆文件”的思想, 在linux中要实现网 ...

  6. Linux网络编程入门 (转载)

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

  7. [转] - Linux网络编程 -- 网络知识介绍

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

  8. Linux C 程序 Linux网络编程(21)

    Linux网络编程网络编程必备的理论基础网络模型,地址,端口,TCP/IP协议 TCP/IP协议是目前世界上使用最广泛的网络通信协议日常中的大部分应用使用该系列协议(浏览网页,收发电子邮件,QQ聊天等 ...

  9. 【转】Linux网络编程入门

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

随机推荐

  1. Sublime Text 3 多行游标

    选中要修改的地方ctrl+D ,要跳过不需要修改的选中的就用ctrl+k+d 选中要修改的地方ctrl+D,选中所有要修改的 alt+f3 ctrl+A  ,然后ctrl+shift+L 按住shif ...

  2. vue实现复制功能(项目使用)

    安装依赖 npm install --save vue-clipboard2 用法: import Vue import VueClipboard from 'vue-clipboard2' Vue. ...

  3. 【JavaScript权威指南】——逻辑与(&&)

    三种用法总结: 1.布尔值计算: [成员]={false,true} 2.“真值”,“假值”计算: [假值]={false,null,undefined,0,-0,NaN,""} ...

  4. AngularJS模块——module

    angular.module('myApp',[]) 1.定义模块 2.第一个参数:定义的模块名: 3.第二个参数:依赖列表,也就是可以被注入到模块中的对象列表:依赖的这些模块需要在本模块加载之前由注 ...

  5. 两个线程分别打印 1- 100,A 打印偶数, B打印奇数

    package com.demo.thread; public class PrintNumber { private static Object lock = new Object(); priva ...

  6. VMWare复制虚拟机系统后,模块“Disk”无法启动【转】

    1.找到虚拟机所在的目录 将 .vmx文件打开 将文件vmci0.present = "TRUE" 改为 vmci0.present = "FALSE" 2.删 ...

  7. asp.net mvc网站的发布与IIS配置

    一.安装IIS (如果服务器上已经安装了就跳过) 控制面板——程序——程序功能——打开或关闭windows功能——勾选Inertnet信息服务下面所有选项——确定 二.获取发布文件(如果已经发不好就跳 ...

  8. python 发布

    使用distutils.core.setup函数发布程序 将要发布的包放到mypub的目录下 在mypub目录下创建一个setup.py文件 setup.py文件的设置 from distutils. ...

  9. ForkJoin有参无返回值、有参有返回值实例

    介绍: a . Fork/Join为JKD1.7引入,适用于对大量数据进行拆分成多个小任务进行计算的框架,最后把所有小任务的结果汇总合并得到最终的结果 b . 相关类 public abstract ...

  10. MS Chart 折线图——去除时间中的时、分、秒,按天统计【转】

    MS Chart 折线图——去除时间中的时.分.秒,按天统计   private void Form2_Load(object sender, EventArgs e){            str ...