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

ЖАНРЫ

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

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

Шрифт:

int close(int __fd);

Данной функции нужно передать всего один параметр — дескриптор сокета.

Однако вызов close использовать не рекомендуется из-за специфики его работы: он закрывает сокет грубо, не дожидаясь завершения передачи данных. В результате использования close вероятность повреждения принимаемых или передаваемых данных очень высока. В принципе, использовать close можно на клиенте, но на сервере это недопустимо: сначала нужно использовать shutdown, а потом уже close.

Вызов shutdown используется для завершения

сеанса связи, при этом еще не переданные данные будут переданы другой стороне. Прототип функции:

extern int shutdown(int __fd, int __how) __THROW;

Первый параметр — это дескриптор сокета, а второй может принимать одно из трех значений:

♦ SHUT_RD (или 0) — передать данные, которые еще не переданы, но их отправка уже началась, и больше не принимать данные для чтения.

♦ SHUT_WR (или 1) — передать данные и запретить прием данных через сокет.

♦ SHUT_RDWR (или 2) — передать данные и запретить вообще обмен через сокет — ни приема, ни передачи.

27.3.7. Программа-сервер

В этом пункте мы напишем две программы — сервер и клиент. Программа-сервер после запуска сразу же перейдет в режим ожидания («прослушивания») новых клиентов. Максимальное количество клиентов —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?\n"

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, '\0', 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...\n");

 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\n", 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. */

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