Чтение онлайн

ЖАНРЫ

Linux: Полное руководство

Аллен Питер В.

Шрифт:

 IPPORT_USERRESERVED = 5000

}
;

Нам понадобятся сразу два сокета: первый — это сокет сервера, а через второй сокет мы будем производить обмен данными с клиентом.

int sock1, sock2;

Следующие переменные:

ans_len
используется для хранения размера передаваемой клиентом информации — фактического размера структуры struct sockaddr_in, а
total
— это счетчик числа клиентов, используемый для вывода порядкового номера клиента.

Переменная

buffer
размера BUF_SIZE — это наш буфер для обмена информацией. Нам нужны две структуры типа
sockaddr_in
 — одна для сервера (sin) и одна для клиента (client).

В строке

sock1 = socket(AF_INET, SOСK_STREAM, 0);

мы создаем наш, «серверный», сокет: набор протоколов — TCP/IP, режим — с установлением соединения.

Затем мы инициализируем структуру sin:

memset((char *)&sin, '\0', sizeof(sin));

sin.sin_family = AF_INET; // TCP/IP

sin.sin_addr.s_addr = INADDR_ANY; // можем работать на

// любом адресе

sin.sin_port = SERVER_PORT; // указываем порт (1234)

После создания сокета и инициализации структуры sin, нужно связать наш сокет с адресом и портом сервера:

bind(sock1, (struct sockaddr *)&sin, sizeof(sin));

Оператор

listen(sock1, 3)
означает, что мы будем прослушивать сокет sock1 (порт 1234) и максимальное число клиентов не должно превышать 3.

Как и любой нормальный сервер, мы должны работать в бесконечном цикле, постоянно обрабатывая запросы клиентов. В бесконечном цикле мы:

1. получаем размер структуры client

ans_len = sizeof(client);

2. создаем сокет sock2, через который будем обмениваться данными с клиентом. Если в очереди listen нет клиентов, мы переходим в состояние ожидания

sock2 = accept(sock1, &client, &ans_len);

3. как только подключится клиент, мы отправим ему сообщение MSG_TO_SEND

write(sock2, MSG_TO_SEND, sizeof(MSG_TO_SEND));

4. увеличиваем счетчик клиентов

total+=1;

5. получаем размер прочитанных данных, сами данные записываются в буфер buffer

ans_len = read(sock2, buffer, BUF_SIZE);

6. выводим прочитанные данные на стандартный вывод

write(1, buffer, ans_len);

7. завершаем сеанс связи

shutdown(sock2, 0);

8. закрываем сокет

close(sock2);

Конечно, любой нормальный сервер при поступлении определенных сигналов, например, SIG_HUP, должен корректно перезапуститься или вообще завершить работу. Наш сервер этого не делает — обработку сигналов, я надеюсь, вы можете добавить сами.

Теперь мы можем откомпилировать нашу программу:

$ gcc -о server server.c

Запускаем:

./server

Программа перешла в состояние ожидания новых клиентов.

27.3.8. Программа-клиент

Программа-клиент

несколько проще, чем сервер. Вот ее листинг:

Листинг 27.4. Программа-клиент

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <netdb.h>

#include <memory.h>

#include <stdio.h>

#define SERVER_HOST "localhost"

#define SERVER_PORT 1234

#define CLIENT_PORT 1235

#define MSG "Denis\n"

main {

 int sock;

 int ans_len;

 int BUF_SIZE = 64;

 char buffer[BUF_SIZE];

 struct hostent *h;

 struct sockaddr_in client, server;

 sock = socket(AF_INET, SOCK_STREAM, 0);

 memset((char *)&client, '\0', sizeof(client));

 client.sin_family = AF_INET;

 client.sin_addr.s_addr = INADDR_ANY;

 client.sin_port = CLIENT_PORT;

 bind(sock, (struct sockaddr *)&client, sizeof(client));

 memset((char *)&client, '\0', sizeof(server));

 h = gethostbyname(SERVER_HOST);

 server.sin_family = AF_INET;

 memcpy((char *)&server.sin_addr.h->h_addr, h->h_length);

 server.sin_port = SERVER_PORT;

 connect(sock, &server, sizeof(server));

 ans_len = recv(sock, buffer, BUF_SIZE, 0);

 write(1, buffer, ans_len);

 send(sock, MSG, sizeof(MSG), 0);

 close(sock);

 exit(0);

}

Константа MSG — это сообщение, которое будет передано серверу. Как и в случае с сервером, нам понадобятся две структуры типа sockaddr_in:

struct hostent *h;

struct sockaddr_in client, server;

Структура типа hostent нам нужна для получения адреса сервера.

Создаем сокет, заполняем информацию о клиенте и связываем сокет:

sock = socket(AF_INET, SOCK_STREAM, 0);

memset((char *)&client, '\0' , sizeof(client));

client.sin_family = AF_INET;

client.sin_addr.s_addr = INADDR_ANY;

client.sin_port = CLIENT_PORT;

Поделиться с друзьями: