小知识:Linux下搭建HTTP服务器完成图片显示功能

目录 1. 前言 2. HTTP协议介绍 3. HTTP的消息结构 4. HTTP交互流程 5. 案例代码: 搭建HTTP服务器 6. 最终运行的效果

1. 前言

作为Linux下socket(TCP)网络编程的练习,使用C语言代码搭建一个简单的HTTP服务器,完成与浏览器之间的交互,最终在浏览器上显示一张图片。

2. HTTP协议介绍

HTTP协议本身是基于TCP通信协议来传递数据(HTML 文件, 图片文件-也叫超文本传输协议),HTTP协议必须工作在客户端-服务端架构上(本身底层就是TCP),HTTP 默认端口号为 80(浏览器访问默认就是80端口),但是你也可以改为 8080 或者其他端口(可以手动指定端口)。

HTTP协议是无连接的,也就是限制每次连接只处理一个请求;服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。

3. HTTP的消息结构

客户端向HTTP服务器发送的请求消息格式包括了4个部分: 请求行(request line)、 请求头部(header)、空行、请求数据

%小知识:Linux下搭建HTTP服务器完成图片显示功能-猿站网-插图

下面这个是浏览器的请求,可以对比上面这张图的格式:

?
1
2
3
4
5
6
7
8
GET / HTTP/1.1
Host: 10.0.0.6
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9

%小知识:Linux下搭建HTTP服务器完成图片显示功能-1猿站网-插图

HTTP常用的请求是GETPOST

HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD 方法。

HTTP1.1 新增了五种请求方法: OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。

HTTP服务器向客户端的响应也由四个部分组成,分别是:状态行、消息报头、空行、响应正文。

例如:

?
1
2
3
4
5
“HTTP/1.1 200 OK\r\n”
“Content-type:image/jpeg\r\n”
“Content-Length:1234\r\n”
“\r\n”
“……………正文………….”

上面列出的报文字段含义: HTTP/1.0 200 OK: Http/1.0 表示当前协议为 Http。 1.0 是协议的版本。 200 表示成功

Content-type : 告诉浏览器回送的数据类型

Content-Length: 告诉浏览器报文中实体主体的大小,也就是返回的内容长度

上面字段里回复的状态码一般有好几种,分别是:

200 – 请求成功

301 – 资源(网页等)被永久转移到其它 URL

404 – 请求的资源(网页等)不存在

500 – 内部服务器错误

4. HTTP交互流程

第一次请求是由HTTP客户端(浏览器)发起的,HTTP服务器收到请求后,对请求进行解析,然后完成后续的交互。

如果要在浏览器上显示一张图片,那么交互的流程大致如下:

%小知识:Linux下搭建HTTP服务器完成图片显示功能-2猿站网-插图

%小知识:Linux下搭建HTTP服务器完成图片显示功能-3猿站网-插图

要让浏览器在界面显示一张图片,还得编写一个HTML代码给浏览器,直接用一个图片标签即可。

当前程序使用的HTML代码比较简单,代码下面贴出来了:

?
1
2
3
4
5
6
7
8
9
10
11
12
<! DOCTYPE HTML>
<html>
<head>
<title>jpg</title>
<meta http-equiv=”content-type” content=”text/html; charset=iso-8859-1″ />
</head>
<body>
<center><img src=”www/123.jpg” width=”512px” height=”384px” />
</center>
</body>
</html>

然后还得准备一张JPG图片,作为资源文件,方便传递给浏览器,本地文件结构如下:

%小知识:Linux下搭建HTTP服务器完成图片显示功能-4猿站网-插图

5. 案例代码: 搭建HTTP服务器

下面代码采用多线程形式响应浏览器的请求。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
/*
函数功能: 服务器向客户端发送响应数据
*/
int HTTP_ServerSendFile(int client_fd,char *buff,char *type,char *file)
{
/*1. 打开文件*/
int fd=open(file,2);
if(fd<0)return -1;
/*2. 获取文件大小*/
struct stat s_buff;
fstat(fd,&s_buff);
/*3. 构建响应头部*/
sprintf(buff,”HTTP/1.1 200 OK\r\n”
“Content-type:%s\r\n”
“Content-Length:%d\r\n”
“\r\n”,type,s_buff.st_size);
/*4. 发送响应头*/
if(write(client_fd,buff,strlen(buff))!=strlen(buff))return -2;
/*5. 发送消息正文*/
int cnt;
while(1)
{
cnt=read(fd,buff,1024);
if(write(client_fd,buff,cnt)!=cnt)return -3;
if(cnt!=1024)break;
}
return 0;
}
/*线程工作函数*/
void *thread_work_func(void *argv)
{
int client_fd=*(int*)argv;
free(argv);
unsigned int cnt;
unsigned char buff[1024];
//读取浏览器发送过来的数据
cnt=read(client_fd,buff,1024);
buff[cnt]=\0;
printf(“%s\n”,buff);
if(strstr(buff,”GET / HTTP/1.1″))
{
HTTP_ServerSendFile(client_fd,buff,”text/html”,”www/image_text.html”);
}
else if(strstr(buff,”GET /www/123.jpg HTTP/1.1″))
{
HTTP_ServerSendFile(client_fd,buff,”image/jpeg”,”www/888.jpg”);
}
else if(strstr(buff,”GET /favicon.ico HTTP/1.1″))
{
HTTP_ServerSendFile(client_fd,buff,”image/x-icon”,”www/1.ico”);
}
close(client_fd);
//退出线程
pthread_exit(NULL);
}
int main(int argc,char **argv)
{  
if(argc!=2)
{
printf(“./app <端口号>\n”);
return 0;
}
signal(SIGPIPE,SIG_IGN); //忽略 SIGPIPE 信号–防止服务器异常退出
int sockfd;
/*1. 创建socket套接字*/
sockfd=socket(AF_INET,SOCK_STREAM,0);
int on = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
/*2. 绑定端口号与IP地址*/
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(atoi(argv[1])); // 端口号0~65535
addr.sin_addr.s_addr=INADDR_ANY;    //inet_addr(“0.0.0.0”); //IP地址
if(bind(sockfd,(const struct sockaddr *)&addr,sizeof(struct sockaddr))!=0)
{
printf(“服务器:端口号绑定失败.\n”);
}
/*3. 设置监听的数量,表示服务器同一时间最大能够处理的连接数量*/
listen(sockfd,20);
/*4. 等待客户端连接*/
int *client_fd;
struct sockaddr_in client_addr;
socklen_t addrlen;
pthread_t thread_id;
while(1)
{
addrlen=sizeof(struct sockaddr_in);
client_fd=malloc(sizeof(int));
*client_fd=accept(sockfd,(struct sockaddr *)&client_addr,&addrlen);
if(*client_fd<0)
{
printf(“客户端连接失败.\n”);
return 0;
}
printf(“连接的客户端IP地址:%s\n”,inet_ntoa(client_addr.sin_addr));
printf(“连接的客户端端口号:%d\n”,ntohs(client_addr.sin_port));
/*创建线程*/
if(pthread_create(&thread_id,NULL,thread_work_func,client_fd))
{
printf(“线程创建失败.\n”);
break;
}
/*设置线程的分离属性*/
pthread_detach(thread_id);
}
/*5. 关闭连接*/
close(sockfd);
return 0;
}

6. 最终运行的效果

%小知识:Linux下搭建HTTP服务器完成图片显示功能-5猿站网-插图

到此这篇关于Linux下搭建简易的HTTP服务器完成图片显示的文章就介绍到这了,更多相关linux搭建http服务器内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/xiaolong1126626497/article/details/124060201

声明: 猿站网有关资源均来自网络搜集与网友提供,任何涉及商业盈利目的的均不得使用,否则产生的一切后果将由您自己承担! 本平台资源仅供个人学习交流、测试使用 所有内容请在下载后24小时内删除,制止非法恶意传播,不对任何下载或转载者造成的危害负任何法律责任!也请大家支持、购置正版! 。本站一律禁止以任何方式发布或转载任何违法的相关信息访客发现请向站长举报,会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。本网站的资源部分来源于网络,如有侵权烦请发送邮件至:2697268773@qq.com进行处理。
建站知识

小知识:ZooKeeper 实现分布式锁的方法示例

2023-3-10 14:37:39

建站知识

小知识:忘记Grafana不要紧2种Grafana重置admin密码方法详细步骤

2023-3-10 14:52:34

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索