Test thread
Вы не подписаны на эту тему. Подписаться
#include "ftp_server.h" #include "debuglog.h" #include "constants.h" #include "client_processor.h" #include <sys/socket.h> #include <sys/types.h> #include <errno.h> #include <memory.h> #include <netdb.h> #include <unistd.h> #include <arpa/inet.h> #include <cstdlib> // Конструктор. FTPServer::FTPServer() { } // Закрывает сокет. (файловый дескриптор) void FTPServer::CloseSocket(int socket) { if (-1 == close(socket)) { DEBUGLOG((string) "Can't process close. " + strerror(errno)); throw(string) "Can't process close. " + strerror(errno); } } // Получает адрес по объекту структуры sockaddr. string FTPServer::GetAddress(struct sockaddr *sa) { // Указатель на структуру sockaddr_in. struct sockaddr_in *sin; // Указатель на строку. const char *addr; // Буфер для адреса. char abuf[INET_ADDRSTRLEN]; // Преобразуем структуру sockaddr в структуру sockaddr_in sin = (struct sockaddr_in *) (sa); // Получаем адрес в десятично-точечной нотации. if (NULL == (addr = inet_ntop(AF_INET, &sin->sin_addr, abuf, INET_ADDRSTRLEN))) { throw(string) "Can't process inet_ntop. " + strerror(errno); } // Возвращаем адрес. return (string) abuf; } // Возвращает порт по структуре sockaddr в виде строки. string FTPServer::GetPort(struct sockaddr * sa) { // Указатель на структуру sockaddr_in. struct sockaddr_in *sin; // Преобразуем одну структуру в другую. sin = (struct sockaddr_in *) (sa); // Преобразуем порт в строку. return cfg.i2s(sin->sin_port); } // Слушает соединения по сокету socketdes, с максимальным числом // подключений backlog. void FTPServer::AcceptConnections(int socketdes, int backlog) { // Сокет, который будет создаваться при подключении // Удаленного адреса. int newsock; // Объект для получения удаленного адреса в сети. struct sockaddr sa; // Переменная для получения размера структуры. socklen_t salen; // Цикл работает бесконечно. while (1) { // Устанавливаем размер структуры. salen = sizeof(sockaddr); // Ждём подключения. if (-1 == (newsock = accept(socketdes, &sa, &salen))) { throw(string) "Can't process accept. " + strerror(errno); } // Получили подключение. Делаем дочерний процесс // для обработки этого клиента. if (0 == fork()) { // Пишем в лог файл, что получили подключение. DEBUGLOG("New connection. Remote address: " + GetAddress(&sa) + " port: " + GetPort(&sa)); // Пытаемся обработать некоторые действия. try { // Закрываем сокет, который слушает. CloseSocket(socketdes); // Создаём объект, для обработки действий клиента. ClientProcessor cp; try { // Инициализирует объект, и выполняет команды // заданные удаленным клиентом. cp.Create(newsock, socketdes - 1, &(struct sockaddr_in &) sa, cfg.GetParam(_FTP_ACCESSDIR_PARAM_)); } catch(string & s) { // Произошла какая-то ошибка. // Завершаем соединение с клиентом. CloseSocket(newsock); // Если это было просто завершение, if (s == "Quit") { // Пишем, что соединение закрыто. DEBUGLOG("Connection closed."); // Завершаемся с успешным кодом возврата. exit(EXIT_SUCCESS); } // Иначе пишем, что не смогли обработать соединение. DEBUGLOG((string) "Can't process remote connection. " + s); // Завершаемся с отрицательным кодом возврата. exit(EXIT_FAILURE); } // Закрываем сокет. Ошибка не произошла. CloseSocket(newsock); } catch(string & s) { CloseSocket(newsock); DEBUGLOG(s); exit(EXIT_FAILURE); } // Пишем, что соединение закрыто. DEBUGLOG("Connection with " + GetAddress(&sa) + " port: " + GetPort(&sa) + " closed."); exit(EXIT_SUCCESS); } // В родительском процессе закрываем сокет, по которому получили подключение. try { CloseSocket(newsock); } catch(string & s) { throw s; } } } // СОздает сокет, который слушает на указанном порте и принимает // максимум backlog соединений. void FTPServer::ListenConnections(int port, int backlog) { // Сокет для прослушивания. int socketdes; // Структура для передачи в некоторые функции. struct sockaddr sa; struct sockaddr_in sin; // Зануляем их. memset(&sa, 0, sizeof(sa)); memset(&sin, 0, sizeof(sin)); // Устанавливаем локальный адрес. sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_ANY); // Укзаываем прослушивающий порт. sin.sin_port = htons(port); // Преобразуем в структуру sockaddr sa = (struct sockaddr &) sin; // Создаем сокет для того, чтобы принимать входящие соединения. if (-1 == (socketdes = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))) { // Не вышло. throw(string) "Can't process socket." + strerror(errno); } // Присваиваем сокету адрес. if (-1 == bind(socketdes, &sa, sizeof(struct sockaddr))) { throw(string) "Can't process bind. " + strerror(errno); } // Устанавливаем "на прослшку" сокет // с заданным количеством максимальных соединений. if (-1 == listen(socketdes, backlog)) { throw(string) "Can't process listen. " + strerror(errno); } try { // Принимаем входящие соединения. AcceptConnections(socketdes, backlog); } catch(string & s) { // Произошла какая-то ошибка. // Кидаем дальше. throw(string) "Can't accept connections. " + s; } } // Запускает сервер. void FTPServer::Start() { // Вначале загружаем конфиг файл. try { cfg.Load(_FTP_CONFIG_FILE_); } catch(string & s) { // Произошла ошибка. Пишем информацию в лог файл. DEBUGLOG((string) "Error while loading config file " + _FTP_CONFIG_FILE_ + ": " + s); // Кидаем сообщение дальше. throw(string) "Can't start FTPServer."; } // Проверяем, чтобы в конфиг файле существовал параметр, означающий // путь к рабочей директории ftp сервера. if (!cfg.ParamExists(_FTP_ACCESSDIR_PARAM_)) { DEBUGLOG((string) "No such param " + _FTP_ACCESSDIR_PARAM_ + " in file config: " + _FTP_CONFIG_FILE_); throw(string) "Can't start FTPServer."; } // Проверяем, чтобы в конфиг файле существовал параметр, означающий // порт на котором необходимо слушать соединения ftp сервера. if (!cfg.ParamExists(_FTP_LISTEN_PORT_PARAM_)) { DEBUGLOG((string) "No such param " + _FTP_LISTEN_PORT_PARAM_ + " in file config: " + _FTP_CONFIG_FILE_); throw(string) "Can't start FTPServer."; } // Проверяем, чтобы в конфиг файле существовал параметр, означающий // порт на котором необходимо слушать соединения ftp сервера. if (!cfg.ParamExists(_FTP_LISTEN_PORT_PARAM_)) { DEBUGLOG((string) "No such param " + _FTP_LISTEN_PORT_PARAM_ + " in file config: " + _FTP_CONFIG_FILE_); throw(string) "Can't start FTPServer."; } // Слушаем соединения. try { ListenConnections(cfg.s2i(cfg.GetParam(_FTP_LISTEN_PORT_PARAM_)), cfg.s2i(cfg. GetParam(_FTP_LISTEN_BACKLOG_PARAM_))); } catch(string & s) { DEBUGLOG((string) "Can't initiate sockets. Reason: " + s) throw(string) "Can't start FTPServer."; } } void FTPServer::Stop() { } <div></div> Редактировано 2011-06-05 21:31:24. |
Я дивы не писал, а они появились и лишние переводы строк. Копипастил свой код, правда в utf |
int main() } Редактировано 2011-06-06 14:16:04. |
<p>#include using namespace std; [i]Preved[/i]</p> |
Версия для печати