В этом пункте мы напишем две программы — сервер и клиент. Программа-сервер после запуска сразу же перейдет в режим ожидания («прослушивания») новых клиентов. Максимальное количество клиентов —3. Как только подключится клиент, сервер отправит ему сообщение «What is your name?», в ответ на которое клиент передаст свое имя — «Denis». Сервер прочитает переданную клиентом информацию и выведет ее на консоль. Клиент, в свою очередь, выведет на консоль запрос сервера.

С целью упрощения исходного кода как сервера, так и клиента, обработку ошибок производить не будем, поэтому будьте готовы к тому, что ваш клиент выдаст сообщение Segmentation fault в ответ на неверно заданные параметры. Я рекомендую в качестве имени сервера использовать localhost и обе программы запускать на одном компьютере — это же только демонстрация.

Вот исходный код программы-сервера:

Листинг 27.3. Программа-сервер

#include <sys/types.h>

#include <netdb.h>

#include <memory.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <stdio.h>

#define SERVER_PORT 1234

#define BUF_SIZE 64

#define MSG_TO_SEND 'What is your name? '

int main() {

 int sock1, sock2;

 int ans_len, total=0;

 char buffer[BUF_SIZE];

 struct sockaddr_in sin, client;

 sock1 = socket(AF_INET, SOCK_STREAM, 0);

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

 sin.sin_family = AF_INET;

 sin.sin_addr.s_addr = INADDR_ANY;

 sin.sin_port = SERVER_PORT;

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

 printf('Server running... ');

 listen(sock1, 3);

 while (1) {

  ans_len = sizeof(client);

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

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

  total+=1;

  ans_len = read(sock2, buffer, BUF_SIZE);

  write(1, buffer, ans_len);

  printf('Client no %d ', total);

  shutdown(sock2, 0);

  close(sock2);

 }

 return 0;

}

Теперь разберемся, что есть что. Сначала мы определяем некоторые макросы: номер порта, который будет прослушивать сервер, размер буфера передаваемых данных и текст запроса клиенту.

Стандартные номера портов определены в файле netinet/in.h:

enum {

 IPPORT_ECHO = 7, /* Echo service. */

 IPPORT_DISCARD = 9, /* Discard transmissions service. */

 IPPORT_SYSTAT = 11, /* System status service. */

 IPPORT_DAYTIME = 13, /* Time of day service. */

 IPPORT_NETSTAT = 15, /* Network status service. */

 IPPORT_FTP = 21, /* File Transfer Protocol. */

 IPPORT_TELNET =23, /* Telnet protocol. */

 IPPORT_SMTP = 25, /* Simple Mail Transfer Protocol. */

 IPPORT_TIMESERVER = 37, /* Timeserver service. */

 IPPORT_NAMESERVER = 42, /* Domain Name Service. */

 IPPORT_WHOIS = 43, /* Internet Whois service. */

 IPPORT_MTP = 57,

 IPPORT_TFTP = 69, /* Trivial File Transfer Protocol. */

 IPPORT_RJE = 77,

 IPPORT_FINGER = 79, /* Finger service. */

 IPPORT_TTYLINK = 87,

 IPPORT_SUPDUP = 95, /* SUPDUP protocol. */

 IPPORT_EXECSERVER = 512, /* execd service. */

 IPPORT_LOGINSERVER = 513, /* rlogind service. */

 IPPORT_CMDSERVER = 514,

 IPPORT_EFSSERVER = 520,

 /* UDP ports. */

 IPPORT_BIFFUDP = 512,

 IPPORT_WHOSERVER = 513,

 IPPORT_ROUTESERVER = 520,

 /* Ports less than this value are reserved

    for privileged processes. */

 IPPORT_RESERVED = 1024,

 /* Ports greater this value are reserved

    for (non-privileged) servers. */

 IPPORT_USERRESERVED = 5000

};

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

int sock1, sock2;

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

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

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату