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


34

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?


33
Tất nhiên là có thể , câu hỏi là; nó có thực tế không
Ed S.

Xem câu hỏi này trên stackoverflow.com.
kevin cline

24
Bạn có thể sử dụng lắp ráp như một ngôn ngữ phía máy chủ nếu bạn quá nghiêng.
Kênh72

8
Hoặc thậm chí BrainF * ck nếu ,đang .được chuyển hướng đến một ổ cắm.
dan04

4
Điều này mang lại những ký ức kinh hoàng về dự án web đầu tiên tôi tham gia. Cổng thông tin CGI đến mã C. Tôi vẫn còn rùng mình khi nghĩ về nó! :-)
Brian Knoblauch

Câu trả lời:


56

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 chính của FastCGI là bằng C và trực tiếp hỗ trợ 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. :)

Xin lưu ý: Các trang web lớn như Amazon.com, eBay và Google sử dụng C ++ cho các bộ phận 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 chuyển đi gần đây khỏi Lisp (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ột máy ảo mã byte.


2
+1 Để trích dẫn các khung khác nhau. Bạn nên thêm rằng các ứng dụng web lớn được cung cấp bởi c ++ (và các ngôn ngữ khác): amazon.com, google.com, bây giờ là facebook.com thông qua hiphop, v.v.
Klaim

7
@Klaim: Nó phổ biến, nhưng nó không có nghĩa là quy tắc. Kiến trúc của Amazon trong lịch sử dựa trên Lisp và chỉ được viết lại gần đây trong C ++. Kiến trúc của Google liên quan đến Java, Python và các công cụ khác gần như thường xuyên như C ++, tất cả vì nhiều lý do. Facebook hiện chỉ sử dụng hiphop vì họ phát hiện ra PHP không có quy mô. :)
greyfade

4
Tôi đồng ý, nhưng tôi muốn nói rằng họ vẫn là những ví dụ nổi tiếng về việc sử dụng C ++ - để trả lời trực tiếp tiêu đề câu hỏi ban đầu.
Klaim

1
@johannes Vấn đề mở rộng quy mô của Facebook xuất phát từ thực tế là họ phải duy trì một trật tự lớn hơn nhiều máy chủ hơn mức cần thiết, đặc biệt là do hiệu suất kém của tập lệnh PHP được tối ưu hóa. Quy mô tuyến tính đơn giản là không đủ tốt cho một cơ sở hạ tầng lớn như vậy. Nhưng hãy nhớ rằng cách tiếp cận "không chia sẻ gì" không dành riêng cho PHP. C và C ++ cũng có thể làm điều đó.
greyfade

1
@amar Điều này có rất ít lợi nhuận ngoại trừ trong 0,1% ứng dụng cần hiệu năng thô đó. Bạn có thể phục vụ trong 1/3 thời gian ở hầu hết các ngôn ngữ khác với sự hỗ trợ ngăn xếp web tốt. Các ngân hàng, nhà quảng cáo web, v.v ... đều phục vụ quy mô lớn mà không cần dùng đến C ++. Ngay cả Facebook. Twitter. Dòng chảy ngăn xếp. Tất cả làm điều đó trong các ngôn ngữ cấp cao hơn. Ở đây để ở lại nhưng nó sẽ không trở thành đa số một lần nữa. Có lẽ là bao giờ.
Rig

18

Tại sao không?

Các OkCupid trang web hẹn hò được tạo ra với 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 là Wt .


11
"Tại sao không "? Bởi vì nó dễ dàng hơn nhiều khi sử dụng một ngôn ngữ có nhiều hỗ trợ hơn cho loại điều này.
Ed S.

5
@Ed S. Như tôi và greyfade đã chỉ ra, có các khung phát triển ứng dụng web với C ++.
Vitor Py

2
Có, nhưng một lần nữa, chúng có dễ sử dụng như các khung được sử dụng phổ biến hơn không? Tôi thành thật hỏi, tôi không phải là nhà phát triển web và tôi chưa bao giờ sử dụng chúng, nhưng có điều gì đó cho tôi biết họ có thể không trưởng thành hoặc được sử dụng rộng rãi như (ví dụ) các đối tác ruby ​​/ python / PHP của họ.
Ed S.

3
@EdS.: Cả Ruby và Python đều không bắt đầu với các khung web. Trong thực tế phải mất một thập kỷ để những người xuất hiện. Các khung là hậu quả đơn thuần của việc đủ người muốn sử dụng ngôn ngữ X cho vấn đề Y. Điều tương tự có thể xảy ra đối với C ++. Lý do chính tại sao nó không: C ++ không được quản lý, mất nhiều thời gian để biên dịch và nói chung có rào cản lối vào cao hơn.
back2dos

1
@ back2dos: Ai nói một trong hai ngôn ngữ được phát triển với web? Tôi chắc chắn không. Tôi đã sử dụng thuật ngữ "hỗ trợ".
Ed S.

11

Nếu bạn dự định viết ứng dụng web của mình bằng C ++, thì sẽ hoàn toàn 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 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 như một máy chủ proxy và thống kê ngược để 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.


9

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 nó:

  1. Giải thích tất cả các đầ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 (nói chung 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).



5

Có vẻ như Microsoft nghĩ rằng nó cũng có thể. Kiểm tra Casablanca , một 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 các dịch vụ REST 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ã REST gốc 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

2

Đối với PHP, bạn có thể viết các phần mở rộng C / C ++ của riêng mình và nhận được cá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, có lẽ tôi sẽ tạo một thư viện C ++ nhỏ, đã giảm tải quá trình xử lý đó cho phần mở rộng và sau đó trả lại kết quả cho PHP và sau đó PHP đưa 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ột 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 không đồng bộ phía máy khách, rời khỏi web UI -browser hoàn toàn có thể sử dụng.


2

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êm thư viện, 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 đã 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ư JavascriptcreateElement

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 đó 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:

  • Đối với 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.ctệp 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. cdvào thư mục chính của bạn và thực hiện những điều này:

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 với /server.outvà điều hướng đếnlocalhost:8080/hello

Làm xong :)



@ Xin chào: Cảm ơn bạn đã chỉ ra giải pháp thay thế Mongoose này, tôi luôn thích các dự án hướng đến cộng đồng. Tôi có thể sẽ thay thế Mongoose bằng Civiletweb trong câu trả lời của mình sau khi tôi kiểm tra kỹ lưỡng.
Xin chào thế giới

0

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 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 / vào ứng dụng của mình.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.