Ниже приведен пример реализации серверной части daytime:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
main(){
int s, clen, rd, proto;
struct sockaddr_in saddr, caddr;
struct sockaddr *sa, *ca;
struct hostent *rhost;
time_t itime;
char buf[2048], *tstr, *host;
sa=&saddr;
ca=&caddr;
// Получаем номер протокола UDP
proto=getprotobyname("udp")->p_proto;
// Создаем сокет
s=socket(PF_INET, SOCK_DGRAM, proto);
if(s<0) {
perror("udps: не удается создать сокет");
exit(1);
}
// Резервируем порт 13
saddr.sin_family=AF_INET;
saddr.sin_addr.s_addr=INADDR_ANY;
saddr.sin_port=htons(13);
if(bind(s, sa, sizeof(saddr))==-1) {
perror("udps: не удается занять порт");
exit(1);
}
caddr.sin_family=AF_INET;
clen=sizeof(caddr);
while(1) {
// Ожидаем поступления запроса
rd=recvfrom(s, buf, 1, 0, ca, &clen);
if(rd==-1){
perror("udps: ошибка при получении данных");
exit(1);
}
// Преобразуем адрес хоста отправителя в его имя
rhost=gethostbyaddr((char*)(&caddr.sin_addr),
sizeof(caddr.sin_addr), AF_INET);
if(h_errno){
printf("gethostbyaddr error: %d\n", h_errno);
host=inet_ntoa(caddr.sin_addr);
}
else{
host=rhost->h_name;
}
// Получаем строку содержащую дату и время
itime=time(NULL);
tstr=ctime(&itime);
// Выводим время поступления запроса,
// адрес и порт отправителя
printf("%s request from %s:%d\n", tstr, host,
htons(caddr.sin_port));
// Отправляем дату и время клиенту
sendto(s, tstr, strlen(tstr), 0, ca, sizeof(caddr));
}
}
Реализация клиентской части приведена ниже. Клиент устанавливает
ограничение на время ожидания поступления данных, посылает
широковещательный запрос и ожидает поступления ответа. Получив ответ
клиент выводит его на экран и ожидает поступления других ответов. Если
функция recv завершается с ошибкой превышения времени ожидания
ответа, то клиент считает что все ответы получены и завершает
выполнение.
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
main(){
int s, so, clen, rd, proto;
struct sockaddr_in saddr, caddr;
struct sockaddr *sa, *ca;
struct hostent *rhost;
struct timeval timeout;
char buf[100], *host;
sa=&saddr;
ca=&caddr;
// Получаем номер протокола UDP
proto=getprotobyname("udp")->p_proto;
// Создаем сокет
s=socket(AF_INET, SOCK_DGRAM, proto);
if(s<0) {
perror("udpc: не удается создать сокет");
exit(1);
}
// Разрешаем отпраку широковещательных пакетов
so=1;
rd=setsockopt(s,SOL_SOCKET,SO_BROADCAST,&so,sizeof(so));
if(rd==-1) {
perror("udpc: не удается установить параметры сокета");
exit(1);
}
// Устанавливаем предельное время ожидания ответа
timeout.tv_sec=3;
timeout.tv_usec=0;
rd=setsockopt(s,SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
if(rd==-1) {
perror("udpc: не удается установить параметры сокета");
exit(1);
}
// Резервируем порт
caddr.sin_family=AF_INET;
caddr.sin_addr.s_addr=INADDR_ANY;
caddr.sin_port=0;
if(bind(s, ca, sizeof(caddr))==-1) {
perror("udpc: не удается занять порт");
exit(1);
}
// Задаем адрес получателя
saddr.sin_family=AF_INET;
saddr.sin_port=htons(13);
saddr.sin_addr.s_addr=INADDR_BROADCAST;
clen=sizeof(saddr);
// Отправляем запрос
rd=sendto(s, buf, 1, 0, sa, clen);
if(rd==-1){
perror("udpc: ошибка при отправке запроса");
exit(1);
}
while(1){
// Ожидаем ответ
rd=recvfrom(s ,buf ,99 ,0 ,sa , &clen);
if(rd==-1){
// Если превышено время ожидания ответа, то выход
if(errno==EAGAIN) break;
// Иначе ошибка
perror("udpc: ошибка при получении ответа");
exit(1);
}
buf[rd]=(char)0;
// Преобразуем адрес хоста отправителя в его имя
rhost=gethostbyaddr((char*)(&saddr.sin_addr),
sizeof(saddr.sin_addr), AF_INET);
if(h_errno){
printf("gethostbyaddr error: %d",h_errno);
host=inet_ntoa(caddr.sin_addr);
}
else{
host=rhost->h_name;
}
// Выводим информацию о поступившем ответе
printf("%s - reply from %s\n", buf, host);
}
}