среда, 20 мая 2009 г.
Вебинар от QNX SS "Exactly When Do You Need Realtime?"
21 мая, компания QNX Software Systems проведет бесплатный онлайн-семинар, который должен помочь при выборе операционной системы для встраиваемых систем.
Продолжительность: 1 час, включая вопросы.
Все ли встраиваемые проекты нуждаются в ОСРВ?.. Завтра узнаем.
пятница, 8 мая 2009 г.
К проекту прилагается отличная документация в формате С
Отличная статья про то, как хорошо и полезно уметь читать и читать исходный код:
http://gaperton.livejournal.com/32772.html
Когда я только начинал программировать, у меня совсем не было интернета, а в моем городе не было вменяемой литературы, поэтому я привык пользоваться справкой.
Читая сопроводительные тексты к среде разработки и к библиотекам, наткнулся на следующее высказывание: "Чтобы научиться программировать – нужно читать очень много кода, а писать еще больше".
Документация-документацией, но все же, не помешает (а часто и поможет) знание того, как это работает "под капотом".
http://gaperton.livejournal.com/32772.html
Когда я только начинал программировать, у меня совсем не было интернета, а в моем городе не было вменяемой литературы, поэтому я привык пользоваться справкой.
Читая сопроводительные тексты к среде разработки и к библиотекам, наткнулся на следующее высказывание: "Чтобы научиться программировать – нужно читать очень много кода, а писать еще больше".
Документация-документацией, но все же, не помешает (а часто и поможет) знание того, как это работает "под капотом".
четверг, 7 мая 2009 г.
Написание своего HTTP сервера с использованием libevent
Библиотека libevent содержит в себе простейший асинхронный HTTP сервер, который можно
без особого труда встроить в собственное приложение для обслуживания HTTP запросов.
Для использования этой возможности достаточно добавить в код следующее:
1. Подключить заголовочный файл <evhttp.h>:
2. Инициализировать базу событийного движка:
3. Инициализировать HTTP сервер:
4. Указать, на каком сокете слушать подключения:
5. Выставить callback'и на запросы. Можно добавлять на каждый URI свой обработчик:
6. Выставить обработчик на остальные запросы:
7. Запустить цикл обработки запросов:
Реализация HTTP сервера является потоко-безопасной (thread safe).
Есть еще один нюанс: настоятельно рекомендуется игнорировать сигнал SIGPIPE.
Делается это следующим вызовом:
Описание всех функция для работы с HTTP протоколом
можно найти в документации.
Вот работающий пример простого HTTP сервера, который на все запросы отдает динамическую
страничку с некоторой информацией о клиенте.
Makefile для сборки:
А вот результаты тестирования Apache Benchmark:
Сервер был запущен локально на моем ноутбуке, на сервере результаты конечно же получше.
Но для сотни параллельных запросов – это неплохо.
без особого труда встроить в собственное приложение для обслуживания HTTP запросов.
Для использования этой возможности достаточно добавить в код следующее:
1. Подключить заголовочный файл <evhttp.h>:
#include <evhttp.h>
2. Инициализировать базу событийного движка:
event_base * serv_base = (event_base *)event_init();
3. Инициализировать HTTP сервер:
evhttp * http_server = evhttp_new(serv_base);
4. Указать, на каком сокете слушать подключения:
evhttp_accept_socket(http_server, server_sock);
5. Выставить callback'и на запросы. Можно добавлять на каждый URI свой обработчик:
evhttp_set_cb(http_server, "/news", on_request_news, NULL);
6. Выставить обработчик на остальные запросы:
evhttp_set_gencb(http_server, on_request, NULL);
7. Запустить цикл обработки запросов:
event_base_dispatch(serv_base);
Реализация HTTP сервера является потоко-безопасной (thread safe).
Есть еще один нюанс: настоятельно рекомендуется игнорировать сигнал SIGPIPE.
Делается это следующим вызовом:
signal(SIGPIPE, SIG_IGN);
Описание всех функция для работы с HTTP протоколом
можно найти в документации.
Вот работающий пример простого HTTP сервера, который на все запросы отдает динамическую
страничку с некоторой информацией о клиенте.
/* * \file: http_server.cpp * \description: Simple HTTP server * */ #include <errno.h> #include <event.h> #include <evhttp.h> #include <sys/socket.h> #include <sys/types.h> #include <signal.h> #include <netinet/in.h> #include <arpa/inet.h> #include <iostream> const short SERVER_BACKLOG = 128; const short BUF_LEN = 26; const char RESPONCE[BUF_LEN] = "<H1>Hello there</H1><BR/>"; const char * SERVER_NAME = "Simple HTTP Server"; void on_request(struct evhttp_request *, void *); int main(int argc, char **argv) { if (argc < 3) { std::cout << "Start as:" << std::endl << argv[0] << " host_address port" << std::endl; return 1; } int server_sock = socket(AF_INET, SOCK_STREAM, 0); if (server_sock == -1) { std::cout << "Error socket(): " << strerror(errno) << std::endl; return 1; } u_short port = atol(argv[2]); const char * host = argv[1]; sockaddr_in sa; int on = 1; sa.sin_family = AF_INET; sa.sin_port = htons(port); sa.sin_addr.s_addr = inet_addr(host); if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { std::cout << "Error setsockopt(): " << strerror(errno) << std::endl; return 1; } // Bind server socket to ip:port if (bind(server_sock, (const sockaddr*)&sa, sizeof(sa)) == -1) { std::cout << "Error bind(): " << strerror(errno) << " on: " << host << ":" << port << std::endl; return 1; } // Make server to listen if (listen(server_sock, SERVER_BACKLOG) == -1) { std::cout << "Error listen(): " << strerror(errno) << std::endl; return 1; } // Init events event_base * serv_base = (event_base *)event_init(); evhttp * http_server = evhttp_new(serv_base); // Ignore SIGPIPE signal(SIGPIPE, SIG_IGN); if (evhttp_accept_socket(http_server, server_sock) == -1) { std::cout << "Error evhttp_accept_socket(): " << strerror(errno) << std::endl; return 1; } // Set HTTP request callback evhttp_set_gencb(http_server, on_request, NULL); // Dispatch events event_base_dispatch(serv_base); return 0; } void on_request(struct evhttp_request * req, void * arg) { // Create responce buffer struct evbuffer *evb = evbuffer_new(); if (!evb) { return; } // Add heading text evbuffer_add_printf(evb, "<HTML><HEAD><TITLE>%s Page</TITLE></HEAD><BODY>\n", SERVER_NAME); // Add buffer evbuffer_add(evb, RESPONCE, BUF_LEN); // Add formatted text evbuffer_add_printf(evb, "Your request is <B>%s</B> from <B>%s</B>.<BR/>Your user agent is '%s'\n", req->uri, req->remote_host, evhttp_find_header(req->input_headers, "User-Agent")); // Add footer evbuffer_add_printf(evb, "</BODY></HTML>"); // Set HTTP headers evhttp_add_header(req->output_headers, "Server", SERVER_NAME); evhttp_add_header(req->output_headers, "Connection", "close"); // Send reply evhttp_send_reply(req, HTTP_OK, "OK", evb); // Free memory evbuffer_free(evb); }
Makefile для сборки:
SRCS=http_server.cpp LDFLAGS=-levent CXXFLAGS=-I/usr/local/include -L/usr/local/lib PROG=http_server all: c++ ${SRCS} -o ${PROG} ${LDFLAGS} ${CXXFLAGS} clean: rm -f ${PROG}
А вот результаты тестирования Apache Benchmark:
ab -c 100 -n 1000 "http://192.168.1.110:10000/test" Server Software: SimpleHTTPServer Server Hostname: 192.168.1.110 Server Port: 10000 Document Path: /test Document Length: 199 bytes Concurrency Level: 100 Time taken for tests: 0.185 seconds Complete requests: 1000 Failed requests: 0 Write errors: 0 Total transferred: 308000 bytes HTML transferred: 199000 bytes Requests per second: 5393.74 [#/sec] (mean) Time per request: 18.540 [ms] (mean) Time per request: 0.185 [ms] (mean, across all concurrent requests) Transfer rate: 1622.34 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 5 2.8 5 16 Processing: 5 13 3.9 13 23 Waiting: 2 10 3.9 9 22 Total: 11 18 3.4 18 27 Percentage of the requests served within a certain time (ms) 50% 18 66% 19 75% 20 80% 21 90% 22 95% 24 98% 25 99% 26 100% 27 (longest request)
Сервер был запущен локально на моем ноутбуке, на сервере результаты конечно же получше.
Но для сотни параллельных запросов – это неплохо.
Подписаться на:
Сообщения (Atom)