/** * В.Д.Валединский * Простейший пример TCP клиента и сервера. * * Файлы * cli_tcp.cpp - пример TCP клиента * ser_tcp_select.cpp - пример TCP сервера c использованием select() * ser_tcp_poll.cpp - пример TCP сервера c использованием poll() * ser_tcp_fork.cpp - пример TCP сервера c использованием fork() * ser_tcp_prefork.cpp - пример TCP сервера c использованием fork() * * Клиент в цикле получает с клавиатуры текстовую строку и отсылает * ее на сервер, читает и выводит на экран ответ сервера. * Сервер ждет соединений от клиентов. При установленом * соединении получает строку от клиента, переводит ее в верхний * регистр и отсылает обратно клиенту. Если клиент посылает строку * содержащую слово stop, то сервер закрывает соединение с этим клиентом, * а клиент заканчивает свою работу. * Клиент и сервер печатают на экран протокол своей работы т.е. * разные данные, которые они получают или отсылают. * * Для ясности примеры составлены максимально просто и не анализируют * некорректные ответы и запросы клиента и сервера, возможность переполнения * буферов ввода вывода, неожиданное 'падение' сервера и т.п. * */ #include #include #include #include #include #include #include #include #include #include #include // Определимся с номером порта и другими константами. #define PORT 5555 #define BUFLEN 512 // Две вспомогательные функции для чтения/записи (см. ниже) int readFromClient(int fd, char *buf); void writeToClient (int fd, char *buf); int main (void) { int i, err, opt=1; int sock, new_sock; fd_set active_set, read_set; struct sockaddr_in addr; struct sockaddr_in client; char buf[BUFLEN]; socklen_t size; // Создаем TCP сокет для приема запросов на соединение sock = socket (PF_INET, SOCK_STREAM, 0); if ( sock<0 ) { perror ("Server: cannot create socket"); exit (EXIT_FAILURE); } setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char*)&opt,sizeof(opt)); // Заполняем адресную структуру и // связываем сокет с любым адресом addr.sin_family = AF_INET; addr.sin_port = htons(PORT); addr.sin_addr.s_addr = htonl(INADDR_ANY); err = bind(sock,(struct sockaddr*)&addr,sizeof(addr)); if ( err<0 ) { perror ("Server: cannot bind socket"); exit (EXIT_FAILURE); } // Создаем очередь на 3 входящих запроса соединения err = listen(sock,3); if ( err<0 ) { perror ("Server: listen queue failure"); exit(EXIT_FAILURE); } // Подготавливаем множества дескрипторов каналов ввода-вывода. // Для простоты не вычисляем максимальное значение дескриптора, // а далее будем проверять все дескрипторы вплоть до максимально // возможного значения FD_SETSIZE. FD_ZERO(&active_set); FD_SET(sock, &active_set); // Основной бесконечный цикл проверки состояния сокетов while (1) { // Проверим, не появились ли данные в каком-либо сокете. // В нашем варианте ждем до фактического появления данных. read_set = active_set; if ( select(FD_SETSIZE,&read_set,NULL,NULL,NULL)<0 ) { perror("Server: select failure"); exit (EXIT_FAILURE); } // Данные появились. Проверим в каком сокете. for (i=0; i