http协议户端下载流程

/**************************************************************************************
功能:http协议客户端网络下载测试
时间:2014-03-09
version : V1.0
说明:http协议客户端工作要点
1.创建socketbind本地socket,发起连接connetct ,完成tcp三次握手
2.向服务器发起http请求,即post或get动作,http协议请求格式见
  http协议规范
 3.读http响应,可以判定http 服务器和客户端是否通讯正常,如果失败,
 可以根据错误代码判定不成功原因。
 http 响应和http 错误代码见http协议部分
 4.http响应会返回内容的长度和内容类型,这个信息在在在线业务中是个
 非常有用的信息,比如流媒体是边看边下载,如果要计算流媒体长度
 只能从http响应读取。
***************************************************************************************/
#include <fcntl.h>
#include <sys/syscall.h>
#include <sys/mman.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/types.h>
#include <errno.h>
#include <stdlib.h>

#define SERVER_PORT 5000
#define BUF_MASK 0x1ff
#define BUF_SIZE (188*7*64)
#define O_DIRECT 0x8000

void usage()
{
    printf("Usage: http_test_client: -d <srv-ip> -p <srv-port> -f <content-file> [-h -a -v]\n");
    printf("options are:\n");
    printf(" -d <srv-ip>   # IP address of HTTP Server (e.g. 192.168.1.110)\n");
    printf(" -p <srv-port> # Port of HTTP Server (e.g. 5000)\n");
    printf(" -f <file>     # url of stream; /data/videos prepended (e.g. portugal.mpg) \n");
    printf(" -m            # just leave content in memory, dont write to disk (default: write to file)\n");
    printf(" -v            # print periodic stats (default: no)\n");
    printf(" -h            # prints http_test_client usage\n");
    printf("\n");
}


double difftime1(struct timeval *start, struct timeval *stop)
{
double dt = 1000000.*(stop->tv_sec - start->tv_sec) + (stop->tv_usec - start->tv_usec);
return dt;
}


/* This function creates a TCP connection to server and returns the socket descriptor */
int TcpConnect(char *server, int port, int socket_type)
{
int sd,rc;


struct sockaddr_in localAddr, servAddr;
struct hostent *h;


  printf("TCP - Connection to %s:%d ...\n",server, port);


h = gethostbyname(server);
if (h == NULL) {
perror("Unknown Host");
return (-EINVAL);
}


servAddr.sin_family = h->h_addrtype;
memcpy((char *) &servAddr.sin_addr.s_addr, h->h_addr_list[0],h->h_length);
servAddr.sin_port = htons(port);


/* Open Socket */
sd = socket(AF_INET, socket_type, 0);
if (sd<0) {
perror("Socket Open Err");
return -EINVAL;
}


localAddr.sin_family = AF_INET;
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
localAddr.sin_port = htons(0);


if (bind(sd,(struct sockaddr *) &localAddr, sizeof(localAddr))) {
perror("Socket Bind Err");
return -EINVAL;
}


/* Connect to server */
rc = connect(sd, (struct sockaddr *) &servAddr, sizeof(servAddr));
if (rc<0) {
perror("Connect Error: Server busy or unavailable:");
return -EBUSY;
}


printf("TCP: Connection Success\n");
return sd;
}


#define PKTS_PER_READ 64
#define MAX_BUFFER_SIZE (1316 * PKTS_PER_READ)






#define HTTP_POST_SIZE 2048


int main(int argc, char **argv)
{
char *post;
char *server = NULL;
char *fname = NULL;
int maxrate = 19;
int c;
int sd;
FILE *fp = NULL;
char *p;
char *rbuf;
int  port = 0;
ssize_t n;
unsigned char *buf, *xbuf;
ssize_t bytes = 0;
unsigned long total=0;
unsigned long count=0;
char tok;
ssize_t len;
double dt;
struct timeval start, stop;
int accel_socket = 0;   /* Use Standard Socket */
int dont_write_to_disk = 0;
int verbose = 0;
        char cname ='/';
    while ((c = getopt(argc, argv, "d:p:f:amvh")) != -1) {
        switch (c) {
        case 'd':
            server = optarg;
            break;
        case 'p':
            port = atoi(optarg);
            break;
        case 'f':
            fname = optarg;
            break;
        case 'a':
            accel_socket = 1;
            break;
        case 'm':
            dont_write_to_disk = 1;
            break;
        case 'v':
            verbose = 1;
            break;
        case 'h':
        default:
            usage();
            return -1;
        }
    }


if (port == 0 || server == NULL || fname == NULL) {
printf("Missing Args...\n");
usage();
exit(1);
}


printf("Server %s, Port %d, File %s, Maxrate %d\n",
server, port, fname, maxrate);


xbuf = (unsigned char *) malloc(BUF_SIZE + BUF_MASK);
rbuf = (char *) malloc(1024);
post = (char *) malloc(HTTP_POST_SIZE);


if (xbuf == NULL || rbuf == NULL || post == NULL) {
perror("malloc failure\n");
exit(-1);
}


buf = (unsigned char *) (((unsigned long)xbuf + BUF_MASK) & ~BUF_MASK);


/* Build HTTP Get Request */
n = snprintf(post, HTTP_POST_SIZE,
"GET /%s HTTP/1.1\r\n"
"Host: %s:%d\r\n"
"Rate: %d\r\n"
"PlaySpeed.dlna.org: speed=1\r\n"
"User-Agent: %s Test App\r\n"
"\r\n",
fname, server, port, maxrate, "STDSOCKET" );
printf("Sending HTTP Request:----->[\n%s]\n", post);


/* open file for writing */
if (!dont_write_to_disk) {
p=strrchr(fname,'/');
fname=p+1;
fp = fopen(fname,"wb");
if (!fp) {
perror("File open error:\n");
exit(-1);
}
}


/*TODO: enable O_DIRECT and test, need to change BUF_SIZE*/
/*fcntl(fileno(fp),F_SETFL,O_DIRECT);*/

/* Connect to Server */
sd = TcpConnect(server, port,  SOCK_STREAM);
if (sd < 0) {
printf("Connection to Server Failed, Exiting...\n");
exit(-1);
}
/* Send HTTP Get Request */
n = write(sd, post, strlen(post));
if ((unsigned)n != strlen(post)) {
printf("Failed to write HTTP Get Request: rc %d\n", n);
perror("write(): ");
exit(-1);
}


printf("Succesfully Send HTTP Get Request to to %s:%d\n", server, port);
usleep(10000);


/* Read HTTP Response */
memset(rbuf, 0, 1024);
if ( (n = read(sd, rbuf, 1024)) <= 0) {
printf("Failed to read HTTP Response: rc = %d\n", n);
perror("read(): ");
exit(-1);
}


    rbuf[n] = '\0'; 


/* Scan for end of HTTP header */
p = strstr(rbuf,"\r\n\r\n");
if(!p) {
printf("No HTTP Header\n");
len = 0;
p = rbuf;
tok = 0;
}
else {
p+=4;
tok = *p;
*p = 0;
len = strlen(rbuf);
}


printf("Total response len %d, payload len %d\n", n, n-len);
printf("HTTP Response: -----> [\n%s]\n", rbuf);
*p = tok;


/* write any data that was read part of the initial read */
if (n>len) {
if ( (total = write(fileno(fp), p, n - len)) <= 0 ) {
printf("Failed to write initial payload bytes (%lu)\n", total);
perror("write():\n");
exit(-1);
}
}


/* increase the recv buffer before starting to read the content */
//sockSetRecvParams(sd, accel_socket);
sleep(1);


gettimeofday(&start, NULL);
/* read data from network & write to the file */
while(1) {
if ( (n = read(sd, buf, BUF_SIZE)) <= 0) {
gettimeofday(&stop, NULL);
printf("read failed: n = %d\n", n);
perror("read(): ");
break;
}


gettimeofday(&stop, NULL);
if (dont_write_to_disk) {
            bytes = n;
goto after_write;
        }
if (((bytes = write(fileno(fp), buf, n)) <= 0) || bytes != n) {
printf("Failed to write payload bytes (%d)\n", bytes);
perror("write():\n");
break;
}


after_write:
dt = difftime1(&start, &stop);
total += bytes;
count++;
if (verbose && (count % 100) == 0) {
printf("[%10lu] Received %10lu Bytes in dt = %10.2fusec at rate %2.1f\n", 
count, total, dt, (total * 8. / dt));  
}
}


dt = difftime1(&start, &stop);
printf("Final stats: Received %10lu bytes to %s file in %10.1fusec at %2.1f rate\n", 
total, fname, dt, (total * 8. / dt));
fclose(fp);
free(xbuf);
free(rbuf);
    free(post);
return 0;
}


/********************************************************************************
比如下载一个MP3文件过程如下:


root@ubuntu:/home/hfl/hflsamb/network# ./http_test_client -d 192.168.1.108 -p 80 -f /myserver/wy.mp3 -v   
Server 192.168.1.108, Port 80, File /myserver/wy.mp3, Maxrate 19
Sending HTTP Request:----->[
GET //myserver/wy.mp3 HTTP/1.1
Host: 192.168.1.108:80
Rate: 19
PlaySpeed.dlna.org: speed=1
User-Agent: STDSOCKET Test App


]
TCP - Connection to 192.168.1.108:80 ...
TCP: Connection Success
Succesfully Send HTTP Get Request to to 192.168.1.108:80
Total response len 1024, payload len 773
HTTP Response: -----> [
HTTP/1.1 200 OK
Date: Sun, 09 Mar 2014 10:45:55 GMT
Server: Apache/2.2.22 (Win32)
Last-Modified: Tue, 19 Apr 2011 13:10:17 GMT
ETag: "560000000302d3-40275b-4a1453ac09c0f"
Accept-Ranges: bytes
Content-Length: 4204379
Content-Type: audio/mpeg


]
[       100] Received    3329486 Bytes in dt = 1388794.00usec at rate 19.2
read failed: n = 0
read(): : Success
Final stats: Received    4204379 bytes to wy.mp3 file in  6998282.0usec at 4.8 rate
root@ubuntu:/home/hfl/hflsamb/network# 
*********************************************************************************/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

江海细流

如该文章对你有帮助,请支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值