新聞中心
隨著互聯(lián)網(wǎng)的不斷發(fā)展,網(wǎng)絡(luò)服務(wù)器的重要性愈發(fā)凸顯。Web服務(wù)器是網(wǎng)絡(luò)服務(wù)器中非常重要的一種類型,它可以接受網(wǎng)絡(luò)瀏覽器發(fā)送的HTTP請求,返回相應(yīng)的HTML頁面,從而實(shí)現(xiàn)網(wǎng)站的訪問。因此,Web服務(wù)器一直是計(jì)算機(jī)科學(xué)領(lǐng)域的熱門話題。本文將介紹在Linux平臺下使用C語言編寫Web服務(wù)器的實(shí)現(xiàn)方法。

創(chuàng)新互聯(lián)是一家專注于成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站、外貿(mào)網(wǎng)站建設(shè)與策劃設(shè)計(jì),南皮網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設(shè)10余年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:南皮等地區(qū)。南皮做網(wǎng)站價(jià)格咨詢:18982081108
1. 網(wǎng)絡(luò)協(xié)議和套接字
Web服務(wù)器是一種網(wǎng)絡(luò)服務(wù)器,它與客戶端通過網(wǎng)絡(luò)協(xié)議進(jìn)行通信。HTTP(Hypertext Transfer Protocol,超文本傳輸協(xié)議)是Web服務(wù)器和Web瀏覽器之間廣泛使用的協(xié)議。在C語言中,可以使用套接字(socket)實(shí)現(xiàn)網(wǎng)絡(luò)通信,套接字是對TCP/IP協(xié)議的抽象,它允許不同的進(jìn)程在網(wǎng)絡(luò)上進(jìn)行通信。
2. 基本框架
在C語言中,可以使用多線程技術(shù)實(shí)現(xiàn)Web服務(wù)器的并發(fā)處理。服務(wù)器程序接受客戶端請求后,通過多線程實(shí)現(xiàn)并發(fā)處理請求。下面是一個基本的服務(wù)器框架:
“`
#include
#include
#include
#include
#include
#include
#include
#define MAXLINE 1024
#define SERV_PORT 8000
void *doit(void *);
int mn(int argc, char **argv) {
int listenfd, connfd;
pthread_t tid;
socklen_t clilen;
struct sockaddr_in cliaddr, servaddr;
listenfd = socket(AF_INET, SOCK_STREAM, 0); // 創(chuàng)建socket,指定協(xié)議和地址族
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); // 綁定socket和地址
listen(listenfd, 5); // 監(jiān)聽socket
while (1) {
clilen = sizeof(cliaddr);
connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen); // 接受客戶端連接
pthread_create(&tid, NULL, &doit, (void *)(long)connfd); // 創(chuàng)建線程處理客戶端請求
}
}
void *doit(void *arg) {
int connfd = (int)(long)arg;
char buff[MAXLINE];
ssize_t n;
while ((n = read(connfd, buff, MAXLINE)) > 0) {
write(connfd, buff, n);
}
close(connfd);
return (NULL);
}
“`
上述代碼中,我們創(chuàng)建了一個socket并將其與一個地址綁定,然后調(diào)用listen方法來監(jiān)聽來自客戶端的連接。在這個while循環(huán)中,我們使用accept方法來等待客戶端連接。當(dāng)接受到連接后,我們會為其創(chuàng)建一個線程,然后在該線程中處理客戶端請求。在本例中,我們只是簡單地讀取客戶端發(fā)送過來的信息并將其返回。
3. 處理HTTP請求
當(dāng)接收到來自客戶端的HTTP請求時,服務(wù)器需要解析請求、生成響應(yīng)、返回?cái)?shù)據(jù)。下面是一個簡單的HTTP請求響應(yīng)處理函數(shù):
“`
int get_line(int sock, char *buf, int size) {
int i = 0;
char c = ‘\0’;
int n;
while ((i
n = recv(sock, &c, 1, 0);
if (n > 0) {
if (c == ‘\r’) {
n = recv(sock, &c, 1, MSG_PEEK); // 查看下一個字符
if ((n > 0) && (c == ‘\n’))
recv(sock, &c, 1, 0);
else
c = ‘\n’;
}
buf[i] = c;
i++;
} else
c = ‘\n’;
}
buf[i] = ‘\0’;
return (i);
}
void handl_clinet(int fd) {
char buf[1024];
char method[255];
char url[255];
char path[512];
size_t i, j;
struct stat st;
int cgi = 0;
char *query_string = NULL;
get_line(fd, buf, sizeof(buf));
i = 0; j = 0;
while (!isspace(buf[j]) && (i
method[i] = buf[j];
i++; j++;
}
method[i] = ‘\0’;
if (strcasecmp(method, “GET”) && strcasecmp(method, “POST”)) {
unimplemented(fd);
return;
}
if (strcasecmp(method, “POST”) == 0)
cgi = 1;
i = 0;
while (isspace(buf[j]) && (j
j++;
while (!isspace(buf[j]) && (i
url[i] = buf[j];
i++; j++;
}
url[i] = ‘\0’;
if (strcasecmp(method, “GET”) == 0) {
query_string = url;
while ((*query_string != ‘?’) && (*query_string != ‘\0’))
query_string++;
if (*query_string == ‘?’) {
cgi = 1;
*query_string = ‘\0’;
query_string++;
}
}
sprintf(path, “htdocs%s”, url);
if (path[strlen(path) – 1] == ‘/’)
strcat(path, “index.html”);
if (stat(path, &st) == -1) {
while ((get_line(fd, buf, sizeof(buf)) > 0) && strcmp(“\n”, buf))
;
not_found(fd);
} else {
if ((st.st_mode & S_IFMT) == S_IFDIR)
strcat(path, “/index.html”);
if ((st.st_mode & S_IXUSR) ||
(st.st_mode & S_IXGRP) ||
(st.st_mode & S_IXOTH))
cgi = 1;
if (!cgi)
serve_file(fd, path);
else
execute_cgi(fd, path, method, query_string);
}
close(fd);
}
“`
在這個函數(shù)中,我們首先讀取請求行。然后分析請求方法和URL。如果請求方法是GET,我們從URL中解析出查詢字符串,如果存在,則設(shè)置cgi標(biāo)志。如果請求方法是POST,則需要執(zhí)行CGI程序,設(shè)置cgi標(biāo)志為1。接下來,我們檢查指定的文件是否存在。如果文件不存在,則向客戶端返回404錯誤頁面;如果存在,則服務(wù)端會檢查讀/寫/執(zhí)行權(quán)限,如果可執(zhí)行,則執(zhí)行CGI程序,否則發(fā)送文件內(nèi)容給客戶端。
4. CGI程序
CGI(Common Gateway Interface,通用網(wǎng)關(guān)接口)是一種Web服務(wù)器與程序之間的通用接口標(biāo)準(zhǔn),可以讓程序動態(tài)生成網(wǎng)頁或響應(yīng)請求。在C語言中,我們可以使用cgi程序?qū)崿F(xiàn)動態(tài)頁面生成。下面是一個簡單的cgi程序?qū)崿F(xiàn):
“`
void execute_cgi(int fd, char *path, char *method, char *query_string) {
char buf[1024];
int cgi_output[2];
int cgi_input[2];
pid_t pid;
int status;
int i;
char c;
int numchars = 1;
int content_length = -1;
buf[0] = ‘A’; buf[1] = ‘\0’;
if (strcasecmp(method, “GET”) == 0) {
while ((numchars > 0) && strcmp(“\n”, buf))
numchars = get_line(fd, buf, sizeof(buf));
} else { /* POST */
numchars = get_line(fd, buf, sizeof(buf));
while ((numchars > 0) && strcmp(“\n”, buf)) {
buf[15] = ‘\0’;
if (strcasecmp(buf, “Content-Length:”) == 0) {
content_length = atoi(&(buf[16]));
}
numchars = get_line(fd, buf, sizeof(buf));
}
if (content_length == -1) {
bad_request(fd);
return;
}
}
sprintf(buf, “HTTP/1.0 200 OK\r\n”);
send(fd, buf, strlen(buf), 0);
if (pipe(cgi_output)
cannot_execute(fd);
return;
}
if (pipe(cgi_input)
cannot_execute(fd);
return;
}
if ((pid = fork())
cannot_execute(fd);
return;
}
if (pid == 0) /* 子進(jìn)程:執(zhí)行CGI程序 */ {
char meth_env[255];
char query_env[255];
char length_env[255];
dup2(cgi_output[1], STDOUT_FILENO);
dup2(cgi_input[0], STDIN_FILENO);
close(cgi_output[0]);
close(cgi_input[1]);
sprintf(meth_env, “REQUEST_METHOD=%s”, method);
putenv(meth_env);
if (strcasecmp(method, “GET”) == 0) {
sprintf(query_env, “QUERY_STRING=%s”, query_string);
putenv(query_env);
} else { /* POST */
sprintf(length_env, “CONTENT_LENGTH=%d”, content_length);
putenv(length_env);
}
execl(path, path, NULL);
exit(0);
} else { /* 父進(jìn)程:向CGI程序發(fā)送數(shù)據(jù) */
close(cgi_output[1]);
close(cgi_input[0]);
if (strcasecmp(method, “POST”) == 0) {
for (i = 0; i
recv(fd, &c, 1, 0);
write(cgi_input[1], &c, 1);
}
}
while (read(cgi_output[0], &c, 1) > 0) {
send(fd, &c, 1, 0);
}
close(cgi_output[0]);
close(cgi_input[1]);
wtpid(pid, &status, 0);
}
}
“`
在本例中,我們使用HTTP GET方法向服務(wù)器傳遞參數(shù),然后從QUERY_STRING環(huán)境變量中獲取參數(shù)值。然后,我們使用HTTP POST方法向服務(wù)器傳遞參數(shù),該函數(shù)先讀取Content-Length數(shù)據(jù),然后讀取POST數(shù)據(jù)并將其發(fā)送給子進(jìn)程。在子進(jìn)程中,我們將標(biāo)準(zhǔn)輸出定向到管道,將標(biāo)準(zhǔn)輸入定向到另一個管道,并設(shè)置一些環(huán)境變量。然后,我們執(zhí)行CGI程序并在管道中讀取輸出。父進(jìn)程從管道中讀取輸出,并發(fā)送響應(yīng)數(shù)據(jù)。
5.
相關(guān)問題拓展閱讀:
- 用socket連接網(wǎng)頁如何用Linux C代碼實(shí)現(xiàn),連接成功后,如何用代碼實(shí)現(xiàn)像在IE中一輸入賬號密碼一樣登陸賬號
用socket連接網(wǎng)頁如何用Linux C代碼實(shí)現(xiàn),連接成功后,如何用代碼實(shí)現(xiàn)像在IE中一輸入賬號密碼一樣登陸賬號
有 3 方面的知識:
1. http 的知識,你需要使用 HTTP GET/POST 請網(wǎng)頁
2. 把網(wǎng)頁請求下來,會得塵旁到一個 html,然后解析它
3. 解析網(wǎng)頁之后找到用戶名與密碼字段,最后打包出一個 HTTP POST 請消世求,完成用戶名和密碼提交
4. 服務(wù)器會返回派橋橡一個 HTTP 回應(yīng),你解析相應(yīng)的 html 判斷正確與否
linux c實(shí)現(xiàn)web服務(wù)器的介紹就聊到這里吧,感謝你花時間閱讀本站內(nèi)容,更多關(guān)于linux c實(shí)現(xiàn)web服務(wù)器,Linux平臺C語言編寫Web服務(wù)器的實(shí)現(xiàn)方法,用socket連接網(wǎng)頁如何用Linux C代碼實(shí)現(xiàn),連接成功后,如何用代碼實(shí)現(xiàn)像在IE中一輸入賬號密碼一樣登陸賬號的信息別忘了在本站進(jìn)行查找喔。
成都服務(wù)器租用選創(chuàng)新互聯(lián),先試用再開通。
創(chuàng)新互聯(lián)(www.cdcxhl.com)提供簡單好用,價(jià)格厚道的香港/美國云服務(wù)器和獨(dú)立服務(wù)器。物理服務(wù)器托管租用:四川成都、綿陽、重慶、貴陽機(jī)房服務(wù)器托管租用。
當(dāng)前標(biāo)題:Linux平臺C語言編寫Web服務(wù)器的實(shí)現(xiàn)方法 (linux c實(shí)現(xiàn)web服務(wù)器)
分享路徑:http://m.fisionsoft.com.cn/article/coiehep.html


咨詢
建站咨詢
