Листинг 9.9- Простейший udp- сервер
#define
PORT
1153
#define
BUFSIZE 2048
int
main(int argc, char **argv) {
struct
sockaddr_in myaddr; /* наш
адрес
*/
struct
sockaddr_in remaddr;/* удаленный
адрес
*/
socklen_t
addrlen = sizeof(remaddr); /*длина
адресов
*/
int
recvlen; /* число
полученных
байт
*/
int
fd; /* наш
сокет
*/
unsigned
char buf[BUFSIZE]; /* буфер
приема
данных
*/
/*
создаем
UDP сокет
*/
if
((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("невозможно
создать
сокет\n");
return
0; }
/*
привязываем
сокет
к
любому
IP – адресу
и
специфицированному
порту
*/
memset((char
*)&myaddr, 0, sizeof(myaddr));
myaddr.sin_family
= AF_INET;
myaddr.sin_addr.s_addr
= htonl(INADDR_ANY);
myaddr.sin_port
= htons(PORT);
if
(bind(fd,
(struct sockaddr *)&myaddr, sizeof(myaddr))
< 0) {
perror("bind
failed"); return 0; }
/*
принимаем
в
цикле
данные,
печатаем
то
что
получили
*/
for
(;;) {
printf("ждем
на
порте
%d\n", PORT);
recvlen
= recvfrom(fd, buf, BUFSIZE, 0, (struct sockaddr *)&remaddr,
&addrlen);
printf("получено
%d байт\n",
recvlen);
if
(recvlen > 0) {
buf[recvlen]
= 0; printf("получено
сообщение: \"%s\"\n",
buf);
} }
/*бесконечно
*/
}
Двунаправленный
обмен
В
случае если сервер хочет ответить
клиенту, от которого он принял дейтаграмму
можно воспользоваться адресной
информацией, полученной в результате
вызова recvfrom
(см выше). Данные об адресе и порте
клиента, с которого была отправлена
дейтаграмма помещаются в структуру
remaddr:
recvlen
= recvfrom(s, buf, BUFSIZE, 0, (struct
sockaddr *)&remaddr,
&addrlen);
Сервер
теперь может использовать этот адрес
в функции sendto
и отправить сообщение отправителю.
sendto(s,
buf, strlen(buf), 0, (struct
sockaddr *)&remaddr,
addrlen)
Закрытие
сокета.
В
отличие от TCP
– сокетов нет необходимости вызывать
метод shutdown
для закрытия сокета или уничтожения
соединения (т.к. его фактически нет в
случае UDP).
Тем не менее необходимо освободить
дескриптор сокета в ядре, что может
быть осуществлено при помощи вызова
close().
close(fd);