서버 측에서 "스크립트 언어"로 C ++를 사용하여 웹 개발을 시작하고 싶습니다. 내 서버 인프라는 * nix 기반이므로 Azure에서 C ++로 웹 개발을 수행 할 수 없으며 C ++ / CLI ASP.NET도 적용 할 수 없습니다.
레거시 CGI 응용 프로그램과 별도로 C ++를 사용하여 웹 개발을 수행 할 수 있습니까?
,
있습니다 .
소켓로 리디렉션됩니다.
서버 측에서 "스크립트 언어"로 C ++를 사용하여 웹 개발을 시작하고 싶습니다. 내 서버 인프라는 * nix 기반이므로 Azure에서 C ++로 웹 개발을 수행 할 수 없으며 C ++ / CLI ASP.NET도 적용 할 수 없습니다.
레거시 CGI 응용 프로그램과 별도로 C ++를 사용하여 웹 개발을 수행 할 수 있습니까?
,
있습니다 .
소켓로 리디렉션됩니다.
답변:
물론.
Wt , cppcms , CSP 등을 포함하여 개발을위한 몇 가지 프레임 워크가 있습니다. FastCGI의 기본 구현은 C로되어 있으며 C ++를 포함한 여러 언어를 직접 지원합니다 .
문자열을 구문 분석 할 수있는 모든 프로그래밍 언어는 CGI 또는 서블릿에서 사용할 수 있습니다. C 라이브러리와의 바인딩을 구현할 수있는 모든 언어를 사용하여 ISAPI 또는 Apache 호환 서버용 모듈을 개발할 수도 있습니다.
C ++에서는 특히 쉽지 않으며 훌륭한 템플릿 엔진은 거의 없으며 그 사이도 가능합니다.
물론 이것이 좋은 아이디어인지의 문제는 전적으로 또 다른 문제입니다. :)
참고 : Amazon.com, eBay 및 Google과 같은 주요 웹 사이트는 인프라의 일부로 C ++을 사용합니다. 그러나 Google은 속도가 중요한 시스템에 C ++ 만 사용하고 Amazon.com은 비교적 최근에 Lisp (일부 직원을 화나게 한)와 떨어져 전환했습니다.
Facebook은 이전에 PHP를 C ++로 컴파일했지만 HipHop 컴파일러 (부분적으로 C ++로 작성)는 바이트 코드 가상 머신으로 재구성되었습니다.
왜 안돼?
OkCupid 데이트 사이트는 C ++로 작성됩니다. 다른 예가있을 수 있습니다.
Wt 라는 C ++로 웹 애플리케이션을 개발하기위한 Qt에서 영감을 얻은 툴킷도 있습니다 .
C ++로 웹 응용 프로그램을 작성하려는 경우 웹 응용 프로그램을 CGI로 인터페이스하는 것은 총 낭비입니다.
ASIO (Asynchronous I / O)를 사용하여 비동기식으로 빌드하는 것이 좋습니다. 이를 통해 굉장히 빠른 웹 서비스를 구축 할 수 있습니다 ( 최상의 효과를 위해 리버스 프록시 및 정적 서버 로 nginx와 결합 ). 이를 Wt 와 같은 템플릿 라이브러리와 결합 하면 단일 서버에서 초당 수만 건의 요청을 처리 할 수 있습니다.
이것이 동적 언어 웹 프레임 워크에 대한 실용적인 대안인지 여부는 또 다른 문제입니다.
짧은 대답은 ANYTHING을 사용하여 웹 페이지를 작성하여 입력을 읽고 해석 가능한 출력을 작성할 수 있으며 웹 서버에서 실행할 수 있다는 것입니다.
기술적으로 모든 언어는 CGI 스크립트로 사용할 수 있습니다.
다른 방법들도 있습니다. Perl은 c / c ++ 코드를 감싸는 래퍼 (wrapper)로 구축 될 수 있으며, 둘 사이의 해석 계층 역할을합니다 (C로 평평하게 컴파일 된 perl 모듈은 포함되지 않음).
처음에는 매우 흔했습니다. 1990 년대 후반에 제가 처음으로 작업 한 웹 사이트는 C ++로 작성된 ISAPI 확장이었습니다.
마이크로 소프트도 가능하다고 생각하는 것 같습니다. C ++를 사용하여 Azure에 대한 새로운 도구 집합 인 Casablanca 를 확인하십시오 .
카사 블랑카 (Casablanca)는 클라우드 컴퓨팅이 대표하는 소프트웨어 아키텍처의 급격한 변화를 활용하려는 C ++ 개발자를 지원하는 방법을 모색하기위한 프로젝트입니다.
Casablanca를 통해 얻을 수있는 혜택은 다음과 같습니다.
- HTTP, JSON 및 URI에 대한 비동기 C ++ 바인딩을 제공하여 Windows Vista, Windows 7 및 Windows 8 Consumer Preview의 기본 코드에서 REST 서비스 액세스 지원
- Windows 8 Metro 스타일 앱에서 C ++ HTTP 클라이언트 측 코드를 작성하는 데 도움이되는 Visual Studio 확장 SDK
- Visual Studio 통합을 포함하여 Azure 용 네이티브 코드 REST 작성 지원
- 퍼스트 클래스 PaaS (Platform-as-a-Service) 기능으로 네이티브 클라이언트에서 Azure Blob 및 큐 스토리지에 액세스하기위한 편리한 라이브러리
- C ++ 11 기능을 기반으로 비동기 작업을 구성하기위한 일관되고 강력한 모델
- Erlang 액터 기반 프로그래밍 모델의 C ++ 구현
- 샘플 및 문서 세트
PHP 의 경우 고유 한 C / C ++ 확장을 작성하여 좋은 성능 이점을 얻을 수 있습니다. 내 웹 응용 프로그램에서 CPU를 많이 사용하는 부분이 있다면 그 처리를 확장으로 오프로드 한 다음 C로 결과를 PHP로 반환 한 다음 PHP에서 브라우저로 출력하는 작은 C ++ 라이브러리를 만들 것입니다.
사람들이 종종 고려하지 않는 다른 것은 JavaScript / jQuery와 같은 특정 CPU 처리를 클라이언트 측으로 오프로드하는 것입니다. 웹 서버가 있다면 특정 기능 (일부 데이터 처리)에 대해 CPU 집약적 처리를 수행하려면 3Ghz CPU가 필요할 수 있습니다. 우리 회사는 서버를 계속 운영하기 위해 매달 해당 서버에 대한 비용을 지불하고 있습니다. CPU 집약적 작업을 동시에 실행하는 100 명의 동시 사용자에 대한 작업을 동시에 확장하려면 여러 개의 CPU와 서버가 필요할 수 있으므로 비즈니스 비용이 증가합니다. CPU 집약적 작업을 클라이언트 측에 오프로드하면 웹 사이트를 방문하는 각 사용자가 데이터를 직접 처리 할 수 있으며 서버 기능을 늘릴 필요가 없으므로 비용이 절약됩니다.
결국 100 개 이상의 데스크톱 / 태블릿 / 모바일의 강력한 처리 능력을 통해 처리를 수행하면 매월 비즈니스 비용이 발생하는 데이터 센터에 서버가 앉아있는 것보다 훨씬 많은 성능을 발휘합니다. 잠재적으로 모든 서버가 데이터베이스에서 데이터를 검색하여 데이터베이스에 다시 저장하기 전에 콘텐츠와 데이터의 사전 / 사후 처리 및 유효성 검사를 제공합니다. 분명히 클라이언트 측 코드를 너무 CPU 집약적으로 사용하여 웹 브라우저 UI를 차단 / 고정시킬 수는 없습니다. 서버에 대한 AJAX 요청을 발생시키고 데이터를 검색 한 다음 비동기 적으로 클라이언트 측에서 데이터를 처리하여 웹을 남겨 둘 수 있습니다 -브라우저 UI를 완전히 사용할 수 있습니다.
예, 사용할 수 있습니다. 다른 사람들은 다양한 접근법을 언급했습니다. 여기 내 자신의 접근 방식이 있습니다. 장점은 완전히 이식 가능하고 독립적이며 선택 된 모든 라이브러리는 ANSI C에만 의존한다는 것입니다. Linux 커널 및 C 컴파일러 (및 Busybox, bash 등의 명백한 것들) (또는 Windows 만 필요) 그리고 컴파일러), 추가 라이브러리가 필요 없으며 멋진 설치가 필요하지 않습니다.
결과는 웹 서버와 동적 페이지 생성기 ( "apache"및 "php"를 모두 대체) 인 단일 프로그램이며 sqlite를 통해 데이터베이스에 액세스 할 수 있습니다.
사용 된 라이브러리 :
createElement
이 답변의 나머지 부분은 Linux를위한 완전한 설정 안내서입니다. SQlite와 MiniXML은 모두 선택 사항이지만이 가이드는 전체 설치를 다룹니다. sqlite 또는 MiniXML을 비활성화하려는 경우 필요하지 않은 부분을 주석 처리하는 것은 사용자의 몫입니다.
1. 3 개의 라이브러리를 다운로드하십시오
2. 폴더 준비
sqlite3.c , sqlite3.h
mongoose.c , mongoose.h
mxml.h
3. mxml 컴파일
mxml.c가 누락되었음을 알 수 있습니다. 정적 mxml 라이브러리를 만들어야하기 때문입니다. mxml tar.gz가 다운로드 된 폴더로 이동하여 다음을 수행하십시오.
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.
컴파일이 끝나면 많은 파일이 생성됩니다. 관심있는 유일한 파일은 libmxml.a
해당 파일을 기본 폴더에 복사하는 것입니다 .
3.1 재확인
기본 폴더에 다음이 있는지 확인하십시오.
mongoose.c, mongoose.h
libmxml.a, mxml.h
sqlite.c, sqlite.h
4. main.c
실제 프로그램을 작성 main.c
하고 기본 폴더에 파일을 작성합시다 . 여기에 시작하는 데 필요한 골격이 있습니다.
#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*/
마지막으로 컴파일!
컴파일합시다. cd
기본 폴더에 넣고 다음을 실행하십시오.
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 .
이제로 server.out을 실행 /server.out
하고localhost:8080/hello
완료 :)
여러 임베디드 시스템 (예 : 라우터, 프린터 등)에 C ++ 기반 웹 서버가 있다고 생각합니다.
특히 libonion 과 같은 일부 HTTP 서버 라이브러리를 사용 하여 일부 C 또는 C ++ 프로그램에 웹 기능을 추가하거나 일부 웹 인터페이스가있는 라이트 서버를 개발할 수 있습니다.
일부 사람들은 Ocsigen을 사용하여 Ocaml에서 웹 서버 또는 HTTP 인터페이스를 코딩하고 있습니다. 모든 웹이 PHP 인 것은 아닙니다. 또한 FastCGI를 사용 하면 응용 프로그램에서 / 웹으로 동적 웹 처리를 할 수 있습니다.