Шрифт:
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#define BUFLEN 81
main {
int sockMain, addrLength, msgLength;
struct sockaddr_in servAddr, clientAddr;
char buf[BUFLEN];
/* 1. Создать socket для UDP. */
if ((sockMain = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("Сервер не может открыть socket для UDP.");
exit(1);
}
/* 2. Ввести информацию в структуру данных, используемую для хранения локальных
* IP-адресов и порта. Возложить на bind получение свободных портов. */
bzero((char *)&servAddr, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = 0;
/* 3. Вызвать bind, которая запишет номер используемого порта
* в TCB. */
if (bind(sockMain, &servAddr, sizeof(servAddr))) {
perror("Вызов bind от сервера неудачен.");
exit(1);
}
/* 4. Извлекаем номер порта и используем функцию
* getsockname для копирования порта в servAddr. */
addrLength = sizeof(servAddr);
if ( getsockname(sockMain, &servAddr, &addrLength)) {
perror(Вызов getsockname неудачен.");
exit(1);
}
printf("SERVER: Номер порта is %d\n", ntohs(servAddr.sin_port));
/* 5. Бесконечный цикл ожидания сообщений от клиентов. */
for (;;) {
addrLength = sizeof(clientAddr);
bzero(buf, BUFLEN);
if ((msgLength = recvfrom(sockMain, buf, BUFLEN, 0, &clientAddr, &addrLength)) < 0) {
perror("Плохой socket клиента.");
exit(1);
}
/* 6. Распечатать клиентские IP-адрес и порт вместе с сообщением. */
printf("SERVER: IP-адрес клиента: %s\n",
inet_ntoa(clientAddr.sin_addr));
printf("SERVER: Порт клиента: %d\n",
ntohs(clientAddr.sin_port));
printf("SERVER: Длина сообщения %d\n", msgLength);
printf("SERVER: Сообщение: %s\n\n", buf);
}
}
21.10.1 Вызовы в серверной программе UDP
1. sockMain = socket(AF_NET, SOCK_DGRAM, 0);
Семейство адресов — снова Интернет.
2. bzero((char *)&servAddr, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = 0;
Вызовы инициализации адресной структуры сервера те же, что и в программе для TCP.
3. bind(sockMain, &servAddr, sizeof(servAddr));
Как и прежде, bind получает порт для сервера и записывает значения в TCB. Конечно, по сравнению с TCP, UDP содержит очень мало информации.
4. getsockname(sockMain, &servAddr, &length);
Использовать getsockname, чтобы извлечь присвоенный socket порт.
5. msgLength = recvfrom(sockMain, buf, BUFLEN, 0, &clientAddr, &length);
Вызов recvfrom имеет форму:
recvfrom(дескриптор_socket, входной_буфер, длина_буфера, флаги, исходная_адресная_структура, указатель_на_длину_исходной_адресной_структуры)