Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«Π Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ Π² срСдС Linux. Π’Ρ‚ΠΎΡ€ΠΎΠ΅ ΠΈΠ·Π΄Π°Π½ΠΈΠ΅Β». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 101

Автор Майкл ДТонсон

ΠŸΡ€ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠΈ запроса для чтСния tftp-сСрвСр посылаСт Ρ„Π°ΠΉΠ» (512 Π±Π°ΠΉΡ‚ Π·Π° ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π·). КаТдая Π΄Π΅ΠΉΡ‚Π°Π³Ρ€Π°ΠΌΠΌΠ° содСрТит Π½ΠΎΠΌΠ΅Ρ€ Π±Π»ΠΎΠΊΠ° (нумСрация начинаСтся с Π΅Π΄ΠΈΠ½ΠΈΡ†Ρ‹). Когда ΠΊΠ»ΠΈΠ΅Π½Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ Π±Π»ΠΎΠΊ Π΄Π°Π½Π½Ρ‹Ρ…, содСрТащий ΠΌΠ΅Π½Π΅Π΅ 512 Π±Π°ΠΉΡ‚ΠΎΠ², ΠΎΠ½ Π·Π½Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ Ρ„Π°ΠΉΠ» ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ. ПослС ΠΊΠ°ΠΆΠ΄ΠΎΠΉ Π΄Π΅ΠΉΡ‚Π°Π³Ρ€Π°ΠΌΠΌΡ‹ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ посылаСт ΠΎΡ‚Π²Π΅Ρ‚Π½ΡƒΡŽ Π΄Π΅ΠΉΡ‚Π°Π³Ρ€Π°ΠΌΠΌΡƒ с Π½ΠΎΠΌΠ΅Ρ€ΠΎΠΌ Π±Π»ΠΎΠΊΠ°, ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π°ΡŽΡ‰ΡƒΡŽ, Ρ‡Ρ‚ΠΎ Π΄Π°Π½Π½Ρ‹ΠΉ Π±Π»ΠΎΠΊ ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½. Как Ρ‚ΠΎΠ»ΡŒΠΊΠΎ сСрвСр Π²ΠΈΠ΄ΠΈΡ‚ ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅, ΠΎΠ½ отправляСт ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ Π±Π»ΠΎΠΊ Π΄Π°Π½Π½Ρ‹Ρ….

Основной Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ Π΄Π΅ΠΉΡ‚Π°Π³Ρ€Π°ΠΌΠΌΡ‹ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ Π² строках 17-46. НСкоторыС константы ΡƒΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‚ Ρ‚ΠΈΠΏ посылаСмой Π΄Π΅ΠΉΡ‚Π°Π³Ρ€Π°ΠΌΠΌΡ‹, Π° Ρ‚Π°ΠΊΠΆΠ΅ ΠΊΠΎΠ΄ ошибки, отправляСмой Π² Ρ‚ΠΎΠΌ случаС, Ссли Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Π΅ΠΌΡ‹ΠΉ Ρ„Π°ΠΉΠ» Π½Π΅ сущСствуСт (всС ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅ ошибки ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°ΡŽΡ‚ΡΡ нСпосрСдствСнно сСрвСром). Π‘Ρ‚Ρ€ΡƒΠΊΡ‚ΡƒΡ€Π° struct tftpPacket описываСт внСшний Π²ΠΈΠ΄ Π΄Π΅ΠΉΡ‚Π°Π³Ρ€Π°ΠΌΠΌΡ‹ ΠΈ ΠΊΠΎΠ΄ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ Π·Π° Π΄Π°Π½Π½Ρ‹ΠΌΠΈ, которая зависит ΠΎΡ‚ Ρ‚ΠΈΠΏΠ° Π΄Π΅ΠΉΡ‚Π°Π³Ρ€Π°ΠΌΠΌΡ‹. Π—Π°Ρ‚Π΅ΠΌ логичСскоС объСдинСниС, Π²Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ΅ Π² структуру, опрСдСляСт ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹ Π΄Π΅ΠΉΡ‚Π°Π³Ρ€Π°ΠΌΠΌ для ошибок, Π΄Π°Π½Π½Ρ‹Ρ… ΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² подтвСрТдСния.

ΠŸΠ΅Ρ€Π²Π°Ρ Ρ‡Π°ΡΡ‚ΡŒ main() (строки 156β€”169) создаСт UDP-сокСт ΠΈ устанавливаСт Π½ΠΎΠΌΠ΅Ρ€ локального ΠΏΠΎΡ€Ρ‚Π° с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Π²Ρ‹Π·ΠΎΠ²Π° bind(). ПослСдний являСтся Π»ΠΈΠ±ΠΎ ΠΎΡ„ΠΈΡ†ΠΈΠ°Π»ΡŒΠ½ΠΎΠΉ tftp-слуТбой, Π»ΠΈΠ±ΠΎ ΠΏΠΎΡ€Ρ‚ΠΎΠΌ, ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΌ Π² качСствС СдинствСнного Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π° ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строки ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹. Π’ ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΡ‚ нашСго ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° TCP-сСрвСра здСсь Π½Π΅Ρ‚ нСобходимости Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ Π½ΠΈ listen(), Π½ΠΈ accept(), ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ UDP Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Π±Π΅Π· установки соСдинСний.

ПослС создания сокСта сСрвСр ΠΎΠΆΠΈΠ΄Π°Π΅Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ Π΄Π΅ΠΉΡ‚Π°Π³Ρ€Π°ΠΌΠΌΡ‹ ΠΏΡƒΡ‚Π΅ΠΌ Π²Ρ‹Π·ΠΎΠ²Π° recvfrom(). Ѐункция handleRequest(), которая активизируСтся Π² строкС 181, ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Π΅ΠΌΡ‹ΠΉ Ρ„Π°ΠΉΠ» ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π΅Π³ΠΎ. ПослС этого Π²Ρ‹Π·ΠΎΠ²Π° сСрвСр Π΅Ρ‰Π΅ Ρ€Π°Π· Π°ΠΊΡ‚ΠΈΠ²ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ recvfrom() ΠΈ ΠΎΠΆΠΈΠ΄Π°Π΅Ρ‚ запрос ΠΎΡ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π°.

ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ, располоТСнный ΠΏΠ΅Ρ€Π΅Π΄ Π²Ρ‹Π·ΠΎΠ²ΠΎΠΌ handleRequest(), сообщаСт, Ρ‡Ρ‚ΠΎ Π΄Π°Π½Π½Ρ‹ΠΉ сСрвСр ΠΌΠΎΠΆΠ½ΠΎ Π»Π΅Π³ΠΊΠΎ ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ с ΠΈΡ‚Π΅Ρ€Π°Ρ‚ΠΈΠ²Π½ΠΎΠ³ΠΎ сСрвСра Π½Π° ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½Ρ‹ΠΉ, ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΠ² ΠΊΠ°ΠΆΠ΄ΠΎΠΌΡƒ Π²Ρ‹Π·ΠΎΠ²Ρƒ handleRequest() Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ ΠΊΠ°ΠΊ ΡΠ°ΠΌΠΎΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΠ½ΠΎΠΌΡƒ процСссу.

Π’ Ρ‚ΠΎ врСмя ΠΊΠ°ΠΊ главная Ρ‡Π°ΡΡ‚ΡŒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Π½Π΅ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½Π½Ρ‹ΠΉ UDP-сокСт (ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰ΠΈΠΉ Π»ΡŽΠ±ΠΎΠΌΡƒ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Ρƒ соСдинСниС с Π½ΠΈΠΌ), handleSocket() примСняСт для прСобразования Ρ„Π°ΠΉΠ»Π° ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½Π½Ρ‹ΠΉ UDP-сокСт[144]. ПослС Π°Π½Π°Π»ΠΈΠ·Π° ΠΈΠΌΠ΅Π½ΠΈ Ρ„Π°ΠΉΠ»Π°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ, ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΡΡ‚ΠΈ Ρ€Π΅ΠΆΠΈΠΌΠ° прСобразования Π² строкС 93 создаСтся сокСт с Ρ‚Π΅ΠΌ ΠΆΠ΅ самым сСмСйством, Ρ‚ΠΈΠΏΠΎΠΌ ΠΈ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»ΠΎΠΌ, с ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌΠΈ ΠΊΠΎΠ½Ρ‚Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Π» сСрвСр. Π—Π°Ρ‚Π΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ connect() для установки ΡƒΠ΄Π°Π»Π΅Π½Π½ΠΎΠ³ΠΎ ΠΊΠΎΠ½Ρ†Π° сокСта Π½Π° Ρ‚ΠΎΠΌ адрСсС, ΠΎΡ‚ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ поступил запрос Π½Π° Ρ„Π°ΠΉΠ», ΠΈ начинаСтся ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π° Ρ„Π°ΠΉΠ»Π°. ПослС ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Π±Π»ΠΎΠΊΠ° сСрвСр ΠΎΠΆΠΈΠ΄Π°Π΅Ρ‚ ΠΏΠ°ΠΊΠ΅Ρ‚ подтвСрТдСния, ΠΏΡ€Π΅ΠΆΠ΄Π΅ Ρ‡Π΅ΠΌ ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠΈΡ‚ΡŒ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Ρƒ. Когда ΠΏΡ€ΠΈΡ…ΠΎΠ΄ΠΈΡ‚ послСдний ΠΏΠ°ΠΊΠ΅Ρ‚ подтвСрТдСния, сСрвСр Π·Π°ΠΊΡ€Ρ‹Π²Π°Π΅Ρ‚ сокСт ΠΈ возвращаСтся ΠΊ Π³Π»Π°Π²Π½ΠΎΠΌΡƒ Ρ†ΠΈΠΊΠ»Ρƒ.

Π”Π°Π½Π½Ρ‹ΠΉ сСрвСр, ΠΊΠ°ΠΊ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ, запускаСтся с СдинствСнным Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΎΠΌ β€” Π½ΠΎΠΌΠ΅Ρ€ΠΎΠΌ ΠΏΠΎΡ€Ρ‚Π°. Для ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚ΡŒ ΡΡ‚Π°Π½Π΄Π°Ρ€Ρ‚Π½ΡƒΡŽ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΡΠΊΡƒΡŽ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ tftp, Π³Π΄Π΅ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ являСтся ΠΈΠΌΠ΅Π½Π΅ΠΌ хоста для соСдинСния (Π½Π΅ΠΏΠ»ΠΎΡ…ΠΈΠΌ Π²Ρ‹Π±ΠΎΡ€ΠΎΠΌ Π±ΡƒΠ΄Π΅Ρ‚ localhost), Π° Π²Ρ‚ΠΎΡ€ΠΎΠΉ β€” Π½ΠΎΠΌΠ΅Ρ€ΠΎΠΌ ΠΏΠΎΡ€Ρ‚Π°, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ сСрвСр. ПослС запуска ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° Π½ΡƒΠΆΠ½ΠΎ Π°ΠΊΡ‚ΠΈΠ²ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ bin, ΠΏΡ€ΠΈ этом Ρ„Π°ΠΉΠ»Ρ‹ Π±ΡƒΠ΄ΡƒΡ‚ Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Ρ‚ΡŒΡΡ Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ octet, Π° Π½Π΅ Π² стандартном Ρ€Π΅ΠΆΠΈΠΌΠ΅ netascii. Как Ρ‚ΠΎΠ»ΡŒΠΊΠΎ это сдСлано, ΠΊΠΎΠΌΠ°Π½Π΄Π° get ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ любой Ρ„Π°ΠΉΠ» ΠΎΡ‚ сСрвСра ΠΊΠ»ΠΈΠ΅Π½Ρ‚Ρƒ.

  1: /* tftpserver.c */

  2:

  3: /* Π­Ρ‚ΠΎ частичная рСализация tftp. Она Π½Π΅ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ Π΄Π°ΠΆΠ΅ Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚Ρ‹

  4:    ΠΈΠ»ΠΈ ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΡƒΡŽ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Ρƒ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ², ΠΈ ΠΎΠ½Π° Π½Π΅ ΠΎΡ‡Π΅Π½ΡŒ Ρ…ΠΎΡ€ΠΎΡˆΠΎ

  5:    ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ Π½Π΅ΠΏΡ€Π΅Π΄Π²ΠΈΠ΄Π΅Π½Π½Ρ‹Π΅ события.*/

  6:

  7: #include <netdb.h>

  8: #include <stdio.h>

  9: #include <stdlib.h>

 10: #include <string.h>

 11: #include <sys/socket.h>

 12: #include <unistd.h>

 13: #include <fcntl.h>

 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)))