计算机网络学习笔记10-HTTP协议

HTTP协议:超文本传输协议,是基于TCP的应用层协议,它规定了浏览器和服务器通信的规则
特点:
1、支持C/S架构
2、简单快速:客户向服务器请求服务时,只需传送请求方法和路径 ,常用方法:GET、POST
3、无连接:每次连接只能处理一个请求
4、无状态:连接之间无论数据传输失败都不会重传

web服务器编写流程
在这里插入图片描述
若服务器本地磁盘无index.html则在调用open打开文件时会出错并通知浏览器

char err[]= "HTTP/1.1 404 Not Found\r\n"            \
                      "Content-Type: text/html\r\n"           \
                      "\r\n"                              \
                      "<HTML><BODY>File not found</BODY></HTML>";

open打开成功则回应浏览器报文

 char head[] = "HTTP/1.1 200 OK\r\n"                     \
                    "Content-Type: text/html\r\n"             \
                    "\r\n";

参考代码(web服务器):

#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>
#include<pthread.h>
#include<unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
char head[] = "HTTP/1.1 200 OK\r\n"						\
				  "Content-Type: text/html\r\n"				\
				  "\r\n";
char err[]=	"HTTP/1.1 404 Not Found\r\n"			\
					"Content-Type: text/html\r\n"			\
					"\r\n"								\
					"<HTML><BODY>File not found</BODY></HTML>";
void *deal_client_fun(void *arg)//arg=new_fd
{
	int new_fd = (int)arg;
	
	//1、recv获取客户端的请求(只需要调用一次)
	unsigned char buf[512]="";
	recv(new_fd,buf,sizeof(buf), 0);
	
	//2、解析buf 提取所请求的文件名
	char file_name[128]="./html/";
	sscanf(buf,"GET /%[^ ]", file_name+7);
	if(file_name[7]=='\0')
		strcpy(file_name,"./html/index.html");
	
	//3、打开本地文件
	int fd = open(file_name, O_RDONLY);
	if(fd < 0)//打开文件失败
	{
		perror("open");
		//发送失败报文给客户端
		send(new_fd, err, strlen(err), 0);
	}
	else//打开本地文件成功
	{
		//发送成功报文 请准备接受
		send(new_fd, head, strlen(head), 0);
		
		//不停的给浏览器客户端 发送文件数据
		while(1)
		{
			//从本地文件读取数据
			unsigned char buf[1024]="";
			int ret = read(fd,buf,sizeof(buf));
			printf("ret=%d\n", ret);
			if(ret<1024)//文件末尾 将数据发送出去
			{
				send(new_fd,buf,ret,0);
				break;
			}
			send(new_fd,buf,ret,0);
		}
		
		//关闭本地文件描述符
		close(fd);
	}
	
	close(new_fd);
	return NULL;
}

//运行的方式:./a.out 8000
int main(int argc,char *argv[])
{
	if(argc != 2)
	{
		printf("./a.out 8000\n");
		return 0;
	}
	
	//1、创建TCP监听套接字
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd < 0)
	{
		perror("socket");
		return 0;
	}
	
	//2、端口复用
	int yes = 1;
	setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,sizeof(yes));
	
	//3、给服务器绑定固定的IP以及端口
	struct sockaddr_in my_addr;
	bzero(&my_addr,sizeof(my_addr));
	my_addr.sin_family = AF_INET;
	my_addr.sin_port = htons(atoi(argv[1]));
	my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	int ret = bind(sockfd, (struct sockaddr *)&my_addr,sizeof(my_addr));
	if(ret == -1)
	{
		perror("bind");
	}
	
	//4、使用listen函数 将套接字 由主动变被动 创建连接队列
	listen(sockfd, 15);
	
	
	//5、while不停的提取客户端 产生已连接套接字
	while(1)
	{
		struct sockaddr_in cli_addr;
		socklen_t cli_len = sizeof(cli_addr);
		int new_fd = accept(sockfd,(struct sockaddr *)&cli_addr , &cli_len);
		
		//遍历客户端的信息ip port
		unsigned short port=ntohs(cli_addr.sin_port);
		char ip[16]="";
		inet_ntop(AF_INET,&cli_addr.sin_addr.s_addr, ip, 16);
		printf("已有客户端:%s:%hu连接上了服务器\n", ip, port);
		
		//创建线程 服务于客户端
		pthread_t tid;
		pthread_create(&tid,NULL, deal_client_fun, (void *)new_fd);
		pthread_detach(tid);
	}
	
	//关闭监听套接字
	close(sockfd);
	return 0;
}

运行结果:
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值