`

C编程实现http协议

阅读更多

大家都很熟悉HTTP协议的应用,因为每天都在网络上浏览着不少东西,也都知道是HTTP协议是相当简单的。每次用thunder之类的下载软件下载网页,当用到那个“用thunder下载全部链接”时总觉得很神奇。

后来想想,其实要实现这些下载功能也并不难,只要按照HTTP协议发送request,然后对接收到的数据进行分析,如果页面上还有href之类的链接指向标志就可以进行深一层的下载了。HTTP协议目前用的最多的是1.1版本,要全面透彻地搞懂它就参考RFC2616文档吧。我是怕rfc文档了的,要看自己去看吧^_^

源代码如下:

/******* http客户端程序 httpclient.c ************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <limits.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <ctype.h>

//////////////////////////////httpclient.c 开始///////////////////////////////////////////


/********************************************
功能:搜索字符串右边起的第一个匹配字符
********************************************/
char * Rstrchr(char * s, char x) {
	int i = strlen(s);
	if(!(*s)) return 0;
	while(s[i-1]) if(strchr(s + (i - 1), x)) return (s + (i - 1)); else i--;
	return 0;
}

/********************************************
功能:把字符串转换为全小写
********************************************/
void ToLowerCase(char * s) {
	while(s && *s) {*s=tolower(*s);s++;}
}

/**************************************************************
功能:从字符串src中分析出网站地址和端口,并得到用户要下载的文件
***************************************************************/
void GetHost(char * src, char * web, char * file, int * port) {
	char * pA;
	char * pB;
	memset(web, 0, sizeof(web));
	memset(file, 0, sizeof(file));
	*port = 0;
	if(!(*src)) return;
	pA = src;
	if(!strncmp(pA, "http://", strlen("http://"))) pA = src+strlen("http://");
	else if(!strncmp(pA, "https://", strlen("https://"))) pA = src+strlen("https://");
	pB = strchr(pA, '/');
	if(pB) {
		memcpy(web, pA, strlen(pA) - strlen(pB));
		if(pB+1) {
			memcpy(file, pB + 1, strlen(pB) - 1);
			file[strlen(pB) - 1] = 0;
		}
	}
	else memcpy(web, pA, strlen(pA));
	if(pB) web[strlen(pA) - strlen(pB)] = 0;
	else web[strlen(pA)] = 0;
	pA = strchr(web, ':');
	if(pA) *port = atoi(pA + 1);
	else *port = 80;
}


int main(int argc, char *argv[])
{
	int sockfd;
	char buffer[1024];
	struct sockaddr_in server_addr;
	struct hostent *host;
	int portnumber,nbytes;
	char host_addr[256];
	char host_file[1024];
	char local_file[256];
	FILE * fp;
	char request[1024];
	int send, totalsend;
	int i;
	char * pt;

	if(argc!=2)
	{
		fprintf(stderr,"Usage:%s web-address\a\n",argv[0]);
		exit(1);
	}
	printf("parameter.1 is: %s\n", argv[1]);
	ToLowerCase(argv[1]);/*将参数转换为全小写*/
	printf("lowercase parameter.1 is: %s\n", argv[1]);

	GetHost(argv[1], host_addr, host_file, &portnumber);/*分析网址、端口、文件名等*/
	printf("webhost:%s\n", host_addr);
	printf("hostfile:%s\n", host_file);
	printf("portnumber:%d\n\n", portnumber);

	if((host=gethostbyname(host_addr))==NULL)/*取得主机IP地址*/
	{
		fprintf(stderr,"Gethostname error, %s\n", strerror(errno));
		exit(1);
	}

	/* 客户程序开始建立 sockfd描述符 */
	if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)/*建立SOCKET连接*/
	{
		fprintf(stderr,"Socket Error:%s\a\n",strerror(errno));
		exit(1);
	}

	/* 客户程序填充服务端的资料 */
	bzero(&server_addr,sizeof(server_addr));
	server_addr.sin_family=AF_INET;
	server_addr.sin_port=htons(portnumber);
	server_addr.sin_addr=*((struct in_addr *)host->h_addr);

	/* 客户程序发起连接请求 */
	if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)/*连接网站*/
	{
		fprintf(stderr,"Connect Error:%s\a\n",strerror(errno));
		exit(1);
	}

	sprintf(request, "GET /%s HTTP/1.1\r\nAccept: */*\r\nAccept-Language: zh-cn\r\n\
					 User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)\r\n\
					 Host: %s:%d\r\nConnection: Close\r\n\r\n", host_file, host_addr, portnumber);
	printf("%s", request);/*准备request,将要发送给主机*/

	/*取得真实的文件名*/
	if(host_file && *host_file) pt = Rstrchr(host_file, '/');
	else pt = 0;

	memset(local_file, 0, sizeof(local_file));
	if(pt && *pt) {
		if((pt + 1) && *(pt+1)) strcpy(local_file, pt + 1);
		else memcpy(local_file, host_file, strlen(host_file) - 1);
	}
	else if(host_file && *host_file) strcpy(local_file, host_file);
	else strcpy(local_file, "index.html");
	printf("local filename to write:%s\n\n", local_file);

	/*发送http请求request*/
	send = 0;totalsend = 0;
	nbytes=strlen(request);
	while(totalsend < nbytes) {
		send = write(sockfd, request + totalsend, nbytes - totalsend);
		if(send==-1) {printf("send error!%s\n", strerror(errno));exit(0);}
		totalsend+=send;
		printf("%d bytes send OK!\n", totalsend);
	}

	fp = fopen(local_file, "a");
	if(!fp) {
		printf("create file error! %s\n", strerror(errno));
		return 0;
	}
	printf("\nThe following is the response header:\n");
	i=0;
	/* 连接成功了,接收http响应,response */
	while((nbytes=read(sockfd,buffer,1))==1)
	{
		if(i < 4) {
			if(buffer[0] == '\r' || buffer[0] == '\n') i++;
			else i = 0;
			printf("%c", buffer[0]);/*把http头信息打印在屏幕上*/
		}
		else {
			fwrite(buffer, 1, 1, fp);/*将http主体信息写入文件*/
			i++;
			if(i%1024 == 0) fflush(fp);/*每1K时存盘一次*/
		}
	}
	fclose(fp);
	/* 结束通讯 */
	close(sockfd);
	exit(0);
}
 


zj@zj:~/C_pram/practice/http_client$ ls

httpclient  httpclient.c

zj@zj:~/C_pram/practice/http_client$ ./httpclient http://www.baidu.com/

parameter.1 is: http://www.baidu.com/

lowercase parameter.1 is: http://www.baidu.com/

webhost:www.baidu.com

hostfile:

portnumber:80


GET / HTTP/1.1

Accept: */*

Accept-Language: zh-cn

User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)

Host: www.baidu.com:80

Connection: Close


local filename to write:index.html


163 bytes send OK!


The following is the response header:

HTTP/1.1 200 OK

Date: Wed, 29 Oct 2008 10:41:40 GMT

Server: BWS/1.0

Content-Length: 4216

Content-Type: text/html

Cache-Control: private

Expires: Wed, 29 Oct 2008 10:41:40 GMT

Set-Cookie: BAIDUID=A93059C8DDF7F1BC47C10CAF9779030E:FG=1; expires=Wed, 29-Oct-38 10:41:40 GMT; path=/; domain=.baidu.com

P3P: CP=" OTI DSP COR IVA OUR IND COM "


zj@zj:~/C_pram/practice/http_client$ ls

httpclient  httpclient.c  index.html

不指定文件名字的话,默认就是下载网站默认的首页了^_^.

分享到:
评论

相关推荐

    c实现ssdp协议

    在C语言中实现SSDP协议,通常涉及以下几个关键知识点: 1. **UDP套接字编程**:SSDP基于UDP(User Datagram Protocol),所以你需要熟悉如何在C语言中创建和操作UDP套接字。这包括使用`socket()`函数创建套接字,`...

    HJ212-2017协议C语言实现,支持协议组包.zip

    4. 网络通信:C语言中可以使用socket编程接口来实现TCP/IP或HTTP协议,处理连接建立、数据发送和接收、断开连接等操作。 5. 错误处理:在实现过程中,应充分考虑各种异常情况,如网络中断、数据解析错误等,并提供...

    HTTP.zip_C http协议_HTTP协议_c语言 http_c语言 http_c语言http协议

    本实例将深入探讨如何使用C语言来实现HTTP协议。 首先,我们需要理解HTTP协议的基本结构。HTTP协议的请求由三部分组成:起始行、请求头和请求体。起始行包含了请求方法(如GET、POST等)和资源URI;请求头包含了...

    ssdp协议c语言实现

    本项目实现了SSDP协议的C语言版本,重点关注了多线程异步接收和发送NOTIFY消息的实现。 在SSDP协议中,主要有两种类型的消息:SEARCH和NOTIFY。SEARCH消息由客户端发送,用于查找网络上的服务或设备;NOTIFY消息由...

    c语言通过http协议下载

    在C语言中实现HTTP下载,首先需要建立一个socket连接到目标服务器。这涉及到socket编程,包括socket创建、绑定、监听和连接等步骤。C语言的socket接口提供了一系列函数,如socket()、connect()、send()和recv()等,...

    C语言实现的websocket

    WebSocket是一种在客户端和服务器之间建立持久连接的网络通信协议,它允许双向通信,即服务器和客户端都可以主动发送数据。...这个过程需要深入理解网络协议和C语言编程,同时也提供了学习和实践网络编程的良好机会。

    C初学者教程 C语言编程-Http服务器(源码).rar

    总结来说,这个C语言编程的HTTP服务器教程为你提供了一个了解网络编程、HTTP协议以及C语言实际应用的宝贵机会。通过实践,你不仅能掌握HTTP服务器的工作原理,还能提升C语言编程技巧,为未来更复杂的网络应用开发...

    基于http协议的客户端下载模块(C语言实现)

    总的来说,这个项目提供了学习C语言网络编程的实践经验,不仅涉及了基本的HTTP协议和C语言编程,还涵盖了网络通信中的许多核心概念,对于提升网络编程能力具有重要意义。通过动手实现这样一个客户端下载模块,你将...

    tcp ip sockets编程 c语言实现 第2版(中英文pdf各一份)

    本书《TCP/IP Sockets编程:C语言实现》第二版,以其通俗易懂的讲解方式,深受程序员们的喜爱,是学习网络编程的经典之作。下面我们将深入探讨其中涉及的知识点。 1. TCP/IP协议栈: TCP/IP协议栈是互联网的基础,...

    rtsp.rar_RTSP c++_c RTSP_rtsp_rtsp 协议 实现_rtsp协议

    这个"rtsp.rar"压缩包包含了一个C++和C语言实现的RTSP协议示例,对于理解RTSP协议的工作原理和编程实现具有很好的参考价值。 RTSP协议主要由以下几个关键部分组成: 1. **命令和响应**:RTSP协议基于请求/响应模型...

    C语言实现的HTTP请求

    ### C语言实现的HTTP请求知识点解析 ... ...本示例代码展示了如何使用C语言来实现一个简单的HTTP GET请求。 #### 二、核心库与函数介绍 1. **stdio.h**:标准输入输出...这对于学习网络编程和HTTP协议有着重要的参考价值。

    C++语言实现网络协议

    然而,实现网络协议也需对协议本身有深入理解,例如TCP/IP协议族的工作原理、HTTP、FTP等常见应用层协议的格式和流程等。只有将这些理论知识与C++编程技术相结合,才能成功地实现一个完整的网络协议。

    C语言的Socket编程例TCP协议

    参考该文章的代码http://www.cnblogs.com/yuqiao/p/5786427.html.socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信。 socket起源于UNIX...

    C语言实现ICMP协议 TCP/IP协议栈 最新完整源代码8.7

    通过仔细阅读和理解源代码,开发者可以学习到如何在C语言环境中构建网络通信协议,这对于网络编程和系统开发具有很高的价值。不过,为了更深入地理解和运用这些代码,还需要具备扎实的计算机网络基础,对TCP/IP协议...

    c 网络编程 简单实现 c语言初学者

    从给定的文件标题、描述、标签以及部分内容中,我们可以提炼出关于C语言网络编程的基础知识点,特别适合C语言初学者。以下是对这些知识点的详细解释: ### 1. Socket概念 Socket是一种通信机制,用于在不同的...

    C语言实现的HTTP服务端代码

    这个项目是大学课程的一部分,旨在锻炼学生的C语言编程能力和对HTTP协议的理解。通过编写服务端代码,学生将深入理解HTTP请求和响应的工作流程,以及如何处理客户端的请求,发送响应数据。C语言的使用让这个过程更具...

    Linux下C语言编程(聊天室)

    综上所述,"Linux下C语言编程(聊天室)"项目涵盖了C语言基础、网络编程、多线程/进程编程、文件操作、协议设计等多个核心领域,对于提升Linux系统开发能力具有很高的实践价值。通过这个项目,开发者不仅可以学习到...

    http download file.zip_HTTP协议下载文件_http c语言_linux http 下载

    在Linux平台上,使用C++语言实现HTTP协议下载文件是一个典型的网络编程任务,涉及到TCP/IP通信、HTTP协议理解和文件I/O操作。以下是对这个主题的详细解释: 1. **HTTP协议**:超文本传输协议(HTTP)是互联网上应用...

    C语言编程的WWW服务器的设计和实现.pdf

    文章指出,这个过程涵盖了计算机网络技术的多个关键领域,包括IP、TCP、HTTP协议的理解与应用,以及C语言编程中的多线程编程、套接字编程、字符串处理和解析等技术。 首先,文章强调了IP协议的重要性,它是互联网层...

Global site tag (gtag.js) - Google Analytics