Майкл Джонсон - Разработка приложений в среде Linux. Второе издание
- Название:Разработка приложений в среде Linux. Второе издание
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2007
- Город:Москва
- ISBN:978-5-8459-1143-8
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Майкл Джонсон - Разработка приложений в среде Linux. Второе издание краткое содержание
Книга известных профессионалов в области разработки коммерческих приложений в Linux представляет собой отличный справочник для широкого круга программистов в Linux, а также тех разработчиков на языке С, которые перешли в среду Linux из других операционных систем. Подробно рассматриваются концепции, лежащие в основе процесса создания системных приложений, а также разнообразные доступные инструменты и библиотеки. Среди рассматриваемых в книге вопросов можно выделить анализ особенностей применения лицензий GNU, использование свободно распространяемых компиляторов и библиотек, системное программирование для Linux, а также написание и отладка собственных переносимых библиотек. Изобилие хорошо документированных примеров кода помогает лучше усвоить особенности программирования в Linux.
Книга рассчитана на разработчиков разной квалификации, а также может быть полезна для студентов и преподавателей соответствующих специальностей.
Разработка приложений в среде Linux. Второе издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
1: /* tftpserver.c */
2:
3: /* Это частичная реализация tftp. Она не поддерживает даже тайм-ауты
4: или повторную передачу пакетов, и она не очень хорошо
5: обрабатывает непредвиденные события.*/
6:
7: #include
8: #include
9: #include
10: #include
11: #include
12: #include
13: #include
14:
15: #include "sockutil.h" /* некоторые служебные функции */
16:
17: #define RRQ 1 /* запрос на чтение */
18: #define DATA 3 /* блок данных */
19: #define ACK 4 /* подтверждение */
20: #define ERROR 5 /* возникла ошибка */
21:
22: /* коды ошибок tftp */
23: #define FILE_NOT_FOUND 1
24:
25: struct tftpPacket {
26: short opcode;
27:
28: union {
29: char bytes[514]; /* самый большой блок, который мы
30: можем обработать, содержит 2 байта
31: для номера блока и 512 для данных */
32: struct {
33: short code;
34: char message[200];
35: } error;
36:
37: struct {
38: short block;
39: char bytes[512];
40: } data;
41:
42: struct {
43: short block;
44: } ack;
45: } u;
46: };
47:
48: void sendError(int s, int errorCode) {
49: struct tftpPacket err;
50: int size;
51:
52: err.opcode = htons(ERROR);
53:
54: err.u.error.code = htons(errorCode); /* файл не найден */
55: switch (errorCode) {
56: case FILE_NOT_FOUND:
57: strcpy(err.u.error.message, "файл не найден");
58: break;
59: }
60:
61: /* 2 байта кода операции, 2 байта кода ошибки, сообщение и '\0' */
62: size = 2 + 2 + strlen(err.u.error.message) + 1;
63: if (send(s, &err, size, 0) != size)
64: die("erarorsend");
65: }
66:
67: void handleRequest(struct addrinfo tftpAddr,
68: struct sockaddr remote, int remoteLen,
69: struct tftpPacket request) {
70: char * fileName;
71: char * mode;
72: int fd;
73: int s;
74: int size;
75: int sizeRead;
76: struct tftpPacket data, response;
77: int blockNum = 0;
78:
79: request.opcode = ntohs(request.opcode);
80: if (request.opcode != RRQ) die("неверный код операции");
81:
82: fileName = request.u.bytes;
83: mode = fileName + strlen(fileName) + 1;
84:
85: /* здесь поддерживается только режим bin */
86: if (strcmp(mode, "octet")) {
87: fprintf(stderr, "неверный режим %s\n", mode);
88: exit(1);
89: }
90:
91: /* требуется передача при помощи сокета того же семейства и типа,
92: с которым мы начинали */
93: if ((s = socket(tftpAddr.ai_family, tftpAddr.ai_socktype,
94: tftpAddr.ai_protocol)) < 0)
95: die("send socket");
96:
97: /* установить удаленный конец сокета на адрес, который
98: инициирует данное соединение */
99: if (connect(s, &remote, remoteLen))
100: die("connect");
101:
102: if ((fd = open(fileName, O_RDONLY)) < 0) {
103: sendError(s, FILE_NOT_FOUND);
104: close(s);
105: return;
106: }
107:
108: data.opcode = htons(DATA);
109: while ((size = read(fd, data.u.data.bytes, 512)) > 0) {
110: data.u.data.block = htons(++blockNum);
111:
112: /* размер составляют 2 байта (код операции), 2 байта (номер блока) и данные*/
113: size += 4;
114: if (send(s, &data, size, 0) != size)
115: die("data send");
116:
117: sizeRead = recv(s, &response, sizeof(response), 0);
118: if (sizeRead < 0) die("recv ack");
119:
120: response.opcode = ntohs(response.opcode);
121: if (response.opcode != ACK) {
122: fprintf(stderr, "непредвиденный код операции в отклике\n");
123: exit(1);
124: }
125:
126: response.u.ack.block = ntohs(response.u.ack.block);
127: if (response.u.ack.block != blockNum) {
128: fprintf(stderr, "получено подтверждение неверного блока\n");
129: exit(1);
130: }
131:
132: /* если блок, который мы только что отправили, содержит
133: меньше 512 байт, то задача выполнена */
134: if (size < 516) break;
135: }
136:
137: close(s);
138: }
139:
140: int main(int argc, char ** argv) {
141: struct addrinfo hints, * addr;
142: char * portAddress = "tftp";
143: int s;
144: int rc;
145: int bytes, fromLen;
146: struct sockaddr from;
147: struct tftpPacket packet;
148:
149: if (argc > 2) {
150: fprintf(stderr, "использование: tftpserver [порт]\n");
151: exit(1);
152: }
153:
154: if (argv[1]) portAddress = argv[1];
155:
156: memset(&hints, 0, sizeof (hints));
157:
158: hints.ai_socktype = SOCK_DGRAM;
159: hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
160: if ((rc = getaddrinfo(NULL, portAddress, &hints, &addr)))
161: fprintf(stderr, "сбой поиска порта %s\n",
162: portAddress);
163:
164: if ((s = socket(addr->ai_family, addr->ai_socktype,
165: addr->ai_protocol)) < 0)
166: die("socket");
167:
168: if (bind(s, addr->ai_addr, addr->ai_addrlen))
169: die("bind");
170:
171: /* Основной цикл состоит из ожидания tftp-запроса, его обработки
172: и затем ожидания следующего запроса. */
173: while (1) {
174: bytes = recvfrom(s, &packet, sizeof(packet), 0, &from,
175: &fromLen);
176: if (bytes < 0) die("recvfrom");
177:
178: /* Если выполнить разветвление перед вызовом handleRequest() и
179: завершить дочерний процесс после возврата функции, то данный
180: сервер будет работать точно как параллельный tftp-сервер */
181: handleRequest(*addr, from, fromLen, packet);
182: }
183: }
17.7. Ошибки сокетов
Некоторые значения errno
встречаются только при работе с сокетами. Ниже приведен список специфических ошибок сокетов вместе с краткими их описаниями.
EADDRINUSE |
Запрашиваемый адрес уже используется и не может быть переприсвоен. |
EADDRNOTAVAIL |
Запрашивается несуществующий адрес. |
EAFNOSUPPORT |
Указано неподдерживаемое семейство адресов. |
ECONNABORTED |
Соединение прервано программным обеспечением. |
ECONNREFUSED |
Удаленная машина отклонила попытку соединения. |
ECONNRESET |
Соединение переустановлено удаленным концом. Это, как правило, указывает на то, что удаленная машина была перезагружена. |
EDESTADDRREQ |
Выполнена попытка передачи данных через сокет без предоставления адреса назначения. Это может происходить только в дейтаграммных сокетах. |
EHOSTDOWN |
Удаленный хост не находится в сети. |
EHOSTUNREACH |
Удаленный хост недоступен. |
EISCONN |
Для сокета уже установлено соединение. |
EMSGSIZE |
Данные, передаваемые через сокет, слишком велики для отправления в одном элементарном сообщении. |
ENETDOWN |
Сетевое соединение прекратилось. |
ENETRESET |
Сеть была сброшена, что вызвало потерю соединения. |
ENETUNREACH |
Указанная сеть недоступна. |
ENOBUFS |
Для обработки запроса доступного пространства буфера недостаточно. |
ENOPROTOOPT |
Выполнена попытка установить неправильную опцию. |
ENOTCONN |
До выполнения операции необходимо установить соединение. |
ENOTSOCK |
Специфическая сокетная операция была направлена на файловый дескриптор, который ссылается не на сокет. |
EPFNOSUPPORT |
Указано неподдерживаемое семейство протоколов. |
EPROTONOSUPPORT |
Запрос был сделан для неподдерживаемого протокола. |
EPROTOTYPE |
Для сокета был указан несоответствующий тип протокола. |
ESOCKTNOSUPPORT |
Выполнена попытка создания неподдерживаемого типа сокета. |
ETIMEDOUT |
Время соединения истекло. |
17.8. Унаследованные сетевые функции
Интервал:
Закладка: