it-swarm-vi.com

C ++ có thể được sử dụng làm ngôn ngữ phát triển web phía máy chủ không?

Tôi muốn tham gia phát triển web bằng C++ làm "ngôn ngữ kịch bản" ở phía máy chủ. Cơ sở hạ tầng máy chủ của tôi dựa trên * nix, do đó, việc phát triển web trong C++ trên Azure là không thể áp dụng và C++/CLI ASP.NET cũng không áp dụng được.

Khác với các ứng dụng CGI cũ, việc phát triển web có thể được thực hiện bằng C++ không?

34
Scott Davies

Chắc chắn rồi.

Thậm chí có một số khung để phát triển chúng, bao gồm Wt , cppcms , CSP và các khung khác. Triển khai tuyến chính của FastCGI là bằng C và hỗ trợ trực tiếp một số ngôn ngữ , bao gồm cả C++.

Bất kỳ ngôn ngữ lập trình nào có thể phân tích các chuỗi có thể được sử dụng trong CGI hoặc một servlet. Bất kỳ ngôn ngữ nào có thể thực hiện các liên kết với các thư viện C cũng có thể được sử dụng để phát triển các mô-đun cho các máy chủ tương thích ISAPI- hoặc Apache.

Nó không đặc biệt dễ dàng trong C++, và các công cụ tạo khuôn tốt rất ít và xa, nhưng nó có thể được thực hiện.

Tất nhiên, câu hỏi liệu đây có phải là một ý tưởng tốt hay không lại là một vấn đề khác. :)

Lưu ý: Các trang web lớn như Amazon.com, eBay và Google sử dụng C++ cho các phần của cơ sở hạ tầng của họ. Tuy nhiên, nhận ra rằng Google chỉ sử dụng C++ cho các hệ thống quan trọng về tốc độ và Amazon.com chỉ mới rời khỏi LISP gần đây (khiến một số nhân viên cấp cao của họ tức giận :).

Facebook trước đây đã biên dịch PHP thành C++, nhưng trình biên dịch HipHop của họ (được viết một phần bằng C++) đã được trang bị lại dưới dạng máy ảo mã byte.

56
greyfade

Tại sao không?

Trang web hẹn hò OkCool được tạo bằng C++. Có lẽ có những ví dụ khác.

Ngoài ra còn có bộ công cụ lấy cảm hứng từ Qt để phát triển các ứng dụng web với C++ có tên Wt .

18
Vitor Py

Nếu bạn dự định viết ứng dụng web của mình bằng C++, thì sẽ rất lãng phí khi giao diện nó dưới dạng CGI.

Đề xuất của tôi sẽ là xây dựng nó không đồng bộ bằng cách sử dụng ASIO (I/O không đồng bộ). Cùng với đó, bạn có thể xây dựng dịch vụ web nhanh chóng (kết hợp với nginx làm proxy ngược và máy chủ thống kê để có hiệu quả tốt nhất); Kết hợp điều đó với thư viện mẫu như Wt và bạn đã sẵn sàng phục vụ hàng chục nghìn yêu cầu mỗi giây từ một máy chủ.

Cho dù đây là thay thế thực tế cho khung web ngôn ngữ động là một vấn đề khác.

11
vartec

Câu trả lời ngắn gọn là, MỌI THỨ có thể được sử dụng để viết một trang web với điều kiện nó có thể đọc đầu vào, viết đầu ra có thể hiểu được và được máy chủ web thực thi.

Về mặt kỹ thuật, bất kỳ ngôn ngữ nào cũng có thể được sử dụng làm tập lệnh CGI cung cấp:

  1. Giải thích tất cả các yếu tố đầu vào và môi trường như được trình bày bởi máy chủ
  2. Đầu ra trong một ngôn ngữ đánh dấu đã biết (thường là html)
  3. Có thể được chạy bởi máy chủ

Cũng có những cách khác nữa. Perl có khả năng được xây dựng như một trình bao bọc xung quanh mã c/c ++, hoạt động như một lớp phiên dịch giữa hai (và điều này không bao gồm các mô-đun Perl được biên dịch thành C).

9
Avatar_Squadron

ban đầu, nó khá phổ biến - các trang web đầu tiên tôi làm việc vào cuối những năm 1990 là các phần mở rộng ISAPI được viết bằng C++ và chúng hoạt động khá tốt.

7
Steven A. Lowe

Có vẻ như Microsoft nghĩ rằng nó cũng có thể. Hãy xem Casablanca là bộ công cụ mới cho (nó xuất hiện) Azure bằng C++.

Casablanca là một dự án để bắt đầu khám phá cách hỗ trợ tốt nhất cho các nhà phát triển C++, những người muốn tận dụng sự thay đổi căn bản trong kiến ​​trúc phần mềm mà điện toán đám mây đại diện.

Đây là những gì bạn nhận được với Casablanca:

  • Hỗ trợ truy cập REST dịch vụ từ mã gốc trên Windows Vista, Windows 7 và Windows 8 Consumer Preview bằng cách cung cấp các liên kết C++ không đồng bộ cho HTTP, JSON và URI
  • SDK tiện ích mở rộng Visual Studio để giúp bạn viết mã phía máy khách HTTP C++ trong ứng dụng kiểu Windows 8 Metro của bạn
  • Hỗ trợ viết mã gốc REST cho Azure, bao gồm tích hợp Visual Studio
  • Các thư viện thuận tiện để truy cập Azure blob và lưu trữ hàng đợi từ các máy khách gốc như một tính năng Nền tảng dịch vụ (PaaS) hạng nhất
  • Một mô hình nhất quán và mạnh mẽ để soạn thảo các hoạt động không đồng bộ dựa trên các tính năng của C++ 11
  • Việc triển khai C++ của mô hình lập trình dựa trên diễn viên Erlang
  • Một bộ mẫu và tài liệu
5
gbjbaanb

Với PHP bạn có thể viết các phần mở rộng C/C++ của riêng bạn và nhận được lợi ích hiệu suất tốt theo cách đó. Nếu tôi có một phần thực sự thâm dụng CPU trong ứng dụng web của mình, tôi có thể sẽ tạo một thư viện C++ nhỏ đã giảm tải quá trình xử lý đó cho tiện ích mở rộng và sau đó trả kết quả về PHP và sau đó PHP xuất nó ra trình duyệt.

Một điều khác mà mọi người thường không cân nhắc là giảm tải một số xử lý CPU cho phía máy khách, ví dụ: JavaScript/jQuery. Nếu tôi có máy chủ web, tôi có thể cần CPU 3Ghz để xử lý chuyên sâu CPU cho một chức năng cụ thể (có thể là một số xử lý dữ liệu). Công ty của tôi đang trả tiền cho máy chủ đó mỗi tháng để duy trì hoạt động. Nếu tôi muốn mở rộng quy mô hoạt động cho 100 người dùng đồng thời chạy nhiệm vụ chuyên sâu CPU đó cùng một lúc thì có lẽ tôi cần nhiều CPU và máy chủ, tăng chi phí cho doanh nghiệp của tôi. Nếu tôi giảm tải nhiệm vụ chuyên sâu CPU đó cho phía máy khách, thì mỗi người dùng truy cập trang web có thể tự xử lý dữ liệu và tôi không phải tăng khả năng máy chủ do đó tiết kiệm tiền cho tôi.

Sau tất cả với sức mạnh tập thể của hơn 100 máy tính để bàn/máy tính bảng/điện thoại di động đang xử lý cho bạn, đó là sức mạnh lớn hơn nhiều so với máy chủ của bạn ngồi trong một trung tâm dữ liệu ở đâu đó làm tốn tiền kinh doanh của bạn mỗi tháng để tiếp tục chạy. Có khả năng sau đó tất cả các máy chủ của bạn sẽ làm sẽ lấy dữ liệu từ cơ sở dữ liệu, phục vụ nội dung và một chút xử lý trước/sau và xác thực dữ liệu trước khi lưu trữ lại cơ sở dữ liệu. Rõ ràng là bạn sẽ không làm cho mã phía máy khách quá nặng CPU có thể chặn/đóng băng giao diện người dùng trình duyệt web, bạn có thể gửi yêu cầu AJAX đến máy chủ, truy xuất dữ liệu và sau đó xử lý dữ liệu phía máy khách không đồng bộ, khiến giao diện người dùng trình duyệt web hoàn toàn có thể sử dụng được.

2
zuallauz

Vâng, nó có thể được sử dụng. Những người khác đã đề cập đến các phương pháp khác nhau. Đây là cách tiếp cận của riêng tôi. Ưu điểm là nó hoàn toàn di động và khép kín, tất cả các thư viện được chọn chỉ phụ thuộc vào ANSI C. Thiết lập nó chỉ yêu cầu Linux Kernel và trình biên dịch C (Và những thứ rõ ràng như Busybox, bash, v.v.) (hoặc Windows và một trình biên dịch), không cần thư viện bổ sung, không cần cài đặt lớn.

Kết quả là một chương trình duy nhất vừa là máy chủ web vừa là trình tạo trang động (Thay thế cả "Apache" và "php"), nó cũng sẽ có quyền truy cập cơ sở dữ liệu qua sqlite.

Thư viện được sử dụng:

  • Mongoose - Máy chủ http
  • Sqlite - Cơ sở dữ liệu SQL
  • MiniXML - Làm cho việc tạo trang động dễ dàng hơn. giống như Javascript của createElement

Phần còn lại của câu trả lời này là một hướng dẫn thiết lập hoàn chỉnh cho Linux. Cả SQlite và MiniXML đều là tùy chọn, nhưng hướng dẫn bao gồm toàn bộ cài đặt. Tùy thuộc vào bạn để nhận xét các phần không cần thiết nếu bạn quan tâm đến việc vô hiệu hóa sqlite hoặc MiniXML.

1. Tải xuống 3 thư viện

2. Chuẩn bị thư mục của bạn

  • Tạo một thư mục trống (Chúng tôi sẽ gọi nó là thư mục chính)
  • Đặt các tệp sau vào đó: [.__.]
    • Từ tar.gz sqlite: sqlite3.c , sqlite3.h
    • Từ Zip Mongoose: mongoose.c , mongoose.h
    • Từ mxml tar.gz: mxml.h

3. Biên dịch mxml

Bạn có thể nhận thấy mxml.c bị thiếu, điều này là do chúng ta cần tạo một thư viện mxml tĩnh. Chuyển đến thư mục nơi mxml tar.gz đã được tải xuống và thực hiện:

tar -xvf mxml-<version>.tar.gz #Extract the tar
cd mxml-<version> #Go to the newly extracted directory
./configure #prepare the compiler
make #compile, you may need to install "make" first.

Sau khi quá trình biên dịch kết thúc, nhiều tệp sẽ được tạo, tệp quan tâm duy nhất đối với chúng tôi là libmxml.a, sao chép tập tin đó vào thư mục chính.

3.1 Doublecheck

Kiểm tra xem thư mục chính có các mục sau:

  • Dành cho cầy mangut: mongoose.c, mongoose.h
  • Đối với mxml: libmxml.a, mxml.h
  • cho sqlite: sqlite.c, sqlite.h

4. chính.c

Hãy tạo chương trình thực tế, tạo một main.c tập tin trong thư mục chính, đây là bộ xương để bạn bắt đầu.

#include <string.h>
#include <stdio.h>

#include "mongoose.h"
#include "mxml.h"
#include "sqlite3.h"

/***Sqlite initialization stuff***/
//comment out everything sqlite related if you don't want sqlite, including the callback function and the include "sqlite3.h"
static int callback(void * custom, int argc, char **argv, char **azColName);
char *zErrMsg = 0;
sqlite3 *db;
int rc;

/***Just some laziness shortcut functions I made***/
typedef mxml_node_t * dom; //type "dom" instead of "mxml_node_t *"
#define c mxmlNewElement   //type "c" instead of "mxmlNewElement"
inline void t(dom parent,const char *string) //etc
{
    mxmlNewText(parent, 0, string);
}

//type "sa" instead of "mxmlElementSetAttr"
inline void sa(dom element,const char * attribute,const char * value) 
{
    mxmlElementSetAttr(element,attribute,value);
}




//The only non boilerplate code around in this program is this function
void serve_hello_page(struct mg_connection *conn)
{
    char output[1000];
    mg_send_header(conn,"Content-Type","text/html; charset=utf-8");
    mg_printf_data(conn, "%s", "<!DOCTYPE html>");
    //This literally prints into the html document


    /*Let's generate some html, we could have avoided the
     * xml parser and just spat out pure html with mg_printf_data
     * e.g. mg_printF_data(conn,"%s", "<html>hello</html>") */

    //...But xml is cleaner, here we go:
            dom html=mxmlNewElement(MXML_NO_PARENT,"html");
                dom head=c(html,"head");
                    dom meta=c(head,"meta");
                    sa(meta,"charset","utf-8");
                dom body=c(html,"body");
                    t(body,"Hello, world<<"); //The < is auto escaped, neat!
                    c(body,"br");
                    t(body,"Fred ate bred");    
                dom table=c(body,"table");
                sa(table,"border","1");

                //populate the table via sqlite
                rc = sqlite3_exec(db, "SELECT * from myCoolTable", callback, table, &zErrMsg);
                if( rc!=SQLITE_OK )
                {
                    fprintf(stderr, "SQL error: %s\n", zErrMsg);
                    sqlite3_free(zErrMsg);
                }

            mxmlSaveString (html,output,1000,  MXML_NO_CALLBACK);
            mg_printf_data(conn, "%s", output);
            mxmlDelete(html); 
}

//sqlite callback
static int callback(void * custom, int argc, char **argv, char **azColName)
{
    //this function is executed for each row
    dom table=(dom)custom;

    dom tr=c(table,"tr");
    dom td;
    int i;
    for(i=0; i<argc; i++)
    {
        td=c(tr,"td");
        if (argv[i])
            t(td, argv[i]);
        else
            t(td, "NULL");

        printf("%s == %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
    }
     printf("\n");
     return 0;
}


static int event_handler(struct mg_connection *conn, enum mg_event ev)
{
    if (ev == MG_AUTH)
    {
        return MG_TRUE;   // Authorize all requests
    }
    else if (ev == MG_REQUEST)
    {
        if (!strcmp(conn->uri, "/hello"))
        {
            serve_hello_page(conn);
            return MG_TRUE;   // Mark as processed
        }
    }
    return MG_FALSE;  // Rest of the events are not processed

}

int main(void)
{
    struct mg_server *server = mg_create_server(NULL, event_handler);
    //mg_set_option(server, "document_root", "."); //prevent dir listing and auto file serving
    //TODO can I allow file listing without dir listing in a specified directory?
    mg_set_option(server, "listening_port", "8080");


    rc = sqlite3_open("db.sqlite3", &db); 

    if( rc )
    {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        return(1);
    }

    printf("Server is running on port 8080!\n");
    for (;;)
    {
        mg_poll_server(server, 1000);  // Infinite loop, Ctrl-C to stop
    }
    mg_destroy_server(&server);
    sqlite3_close(db);

    return 0;
}




/*
 * useful stuff:
 * mg_send_file(struct mg_connection *, const char *path); - serve the file at *path*/

Cuối cùng, biên dịch!

Hãy biên dịch. cd vào thư mục chính của bạn và thực hiện những điều sau:

gcc -c main.c
gcc -c mongoose.c
gcc -c sqlite3.c
gcc -o server.out main.o mongoose.o sqlite3.o -ldl -lpthread -lmxml -L . 

Bây giờ, thực thi server.out bằng /server.out và điều hướng đến localhost:8080/hello

Làm xong :)

2
Hello World

Tôi đoán rằng một số hệ thống nhúng (ví dụ: bộ định tuyến, máy in, ...) có một số máy chủ web điều khiển C++.

Cụ thể, bạn có thể sử dụng một số thư viện máy chủ HTTP như libonion để thêm một số khả năng web vào một số chương trình C hoặc C++ hoặc để phát triển một máy chủ nhẹ với một số giao diện web.

Một số người đang mã hóa máy chủ Web hoặc giao diện HTTP của họ trong Ocaml bằng cách sử dụng Ocsigen . Không phải mọi thứ trên web là PHP. Và với FastCGI bạn có thể xử lý web động trong/cho ứng dụng của mình.

0