jlzzjlzz亚洲乱熟在线播放

系統城裝機大師 - 唯一官網:www.farandoo.com!

當前位置:首頁 > server > anz > 詳細頁面

Linux下搭建HTTP服務器全過程圖片顯示功能介紹

時間:2022-04-15來源:www.farandoo.com作者:電腦系統城

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)、空行、請求數據

下面這個是瀏覽器的請求,可以對比上面這張圖的格式:

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

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服務器收到請求后,對請求進行解析,然后完成后續的交互。

如果要在瀏覽器上顯示一張圖片,那么交互的流程大致如下:

要讓瀏覽器在界面顯示一張圖片,還得編寫一個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圖片,作為資源文件,方便傳遞給瀏覽器,本地文件結構如下:

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服務器完成圖片顯示的文章就介紹到這了,更多相關linux搭建http服務器內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持腳本之家!

分享到:

相關信息

系統教程欄目

欄目熱門教程

人氣教程排行

站長推薦

熱門系統下載