Дальше: Приложение C. Практические задания Вверх: socket Назад: Приложение А. Реализация протокола

Приложение B. Реализация протокола Daytime с использованием TCP

Теперь рассмотрим реализацию протокола daytime при помощи протокола TCP. Как и в UDP, сервер занимает порт 13 и ожидает поступления запросов на установление соединения. После установления соединения, сервер отправляет клиенту строку, содержащую дату и время, и закрывает соединение. Реализация сервера приведена ниже: #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> main() { int s, c, sz; struct sockaddr_in ssa, csa; struct sockaddr *sp, *cp; struct hostent *rhost; char *host, *tstr; time_t itime; sp=(struct sockaddr *)&ssa; cp=(struct sockaddr *)&csa; sz=sizeof(ssa); // Создаём сокет s=socket(AF_INET, SOCK_STREAM, 0); if(s == -1){ perror("Невозможно создать сокет"); exit(1); } // Резервируем порт 13 ssa.sin_family = AF_INET; ssa.sin_port = htons(13); ssa.sin_addr.s_addr = INADDR_ANY; if(bind(s, sp, sz) == -1){ perror("Невозможно занять порт"); exit(1); } // Переводим сокет в режим ожидания соединения if(listen(s, 0) == -1){ perror("Невозможно перейти в режим ожидания"); exit(1); } while(1){ // Принимаем соединение if((c = accept(s, cp, &sz)) == -1) { perror("Ошибка при выполнении accept"); exit(1); } // Преобразуем адрес хоста отправителя в его имя rhost=gethostbyaddr((char*)(&csa.sin_addr), sizeof(csa.sin_addr), AF_INET); if(h_errno){ printf("gethostbyaddr error: %d\n", h_errno); host=inet_ntoa(csa.sin_addr); } else { host=rhost->h_name; } // Получаем строку, содержащую дату и время if((itime = time(NULL)) < 0){ perror("Не удалось получить время"); exit(1); } tstr = ctime(&itime); // Выводим время поступления запроса, // адрес и порт отправителя printf("%s request from %s:%d\n", tstr, host, htons(csa.sin_port)); // Отправляем дату и время клиенту send(c, tstr, strlen(tstr), 0); // Закрываем соединение close(c); } }

Теперь рассмотрим реализацию клиента. Обратите внимание, что клиент не должен выполнять вызов функции bind, порт выделяется автоматически при выполнении connect. #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #define BUFSZ 128 main(int argc, char *argv[]) { int s, sz, i; struct sockaddr_in ssa; struct sockaddr *sp; struct in_addr sip; char buf[BUFSZ]; sp=(struct sockaddr *)&ssa; sz=sizeof(ssa); if(argc!=2){ // Помощь по использованию команды printf("Использование: %s ip-адрес\n",argv[0]); exit(1); } if(inet_aton(argv[1], &sip) != 1){ printf("Неправильно задан адрес сервера\n"); exit(1); } // Создаём сокет s=socket(AF_INET, SOCK_STREAM, 0); if(s == -1){ perror("Невозможно создать сокет"); exit(1); } // Задаём адрес сервера ssa.sin_family = AF_INET; ssa.sin_port = htons(13); ssa.sin_addr = sip; // Устанавливаем соединение if(connect(s, sp, sz) == -1){ perror("Не удалось установить соединение"); exit(1); } // Получаем данные от сервера while((i=recv(s, buf, BUFSZ, 0)) > 0) write(1, buf, i); }



Zwon
2002-03-24