ื’ืึทื ืฅ-ืคื™ื˜ืฉืขืจื“ ื ืึทืงืขื˜-C I/O ืจืขืึทืงื˜ืึธืจ

ื’ืึทื ืฅ-ืคื™ื˜ืฉืขืจื“ ื ืึทืงืขื˜-C I/O ืจืขืึทืงื˜ืึธืจ

ื”ืงื“ืžื”

ืื™ืš / ืึธ ืจืขืึทืงื˜ืึธืจ (ืื™ื™ืŸ ืคืึธื“ืขื ื’ืขืฉืขืขื ื™ืฉ ืฉืœื™ื™ืฃ) ืื™ื– ืึท ืžื•ืกื˜ืขืจ ืคึฟืึทืจ ืฉืจื™ื™ื‘ืŸ ื”ื•ื™ืš-ืžืึทืกืข ื•ื•ื™ื™ื›ื•ื•ืืจื’, ื’ืขื ื™ืฆื˜ ืื™ืŸ ืคื™ืœืข ืคืึธืœืงืก ืกืึทืœื•ืฉืึทื ื–:

ืื™ืŸ ื“ืขื ืึทืจื˜ื™ืงืœ, ืžื™ืจ ื•ื•ืขืœืŸ ืงื•ืงืŸ ืื™ืŸ ื“ื™ ื™ื ืก ืื•ืŸ ืึทื•ืฅ ืคื•ืŸ ืึทืŸ I/O ืจืขืึทืงื˜ืึธืจ ืื•ืŸ ื•ื•ื™ ืขืก ืึทืจื‘ืขื˜, ืฉืจื™ื™ึทื‘ืŸ ืึทืŸ ื™ืžืคึผืœืึทืžืขื ื˜ื™ื™ืฉืึทืŸ ืื™ืŸ ื•ื•ื™ื™ื ื™ืงืขืจ ื•ื•ื™ 200 ืฉื•ืจื•ืช ืคื•ืŸ ืงืึธื“ ืื•ืŸ ืžืึทื›ืŸ ืึท ืคึผืฉื•ื˜ ื”ื˜ื˜ืคึผ ืกืขืจื•ื•ืขืจ ืคึผืจืึธืฆืขืก ืื™ื‘ืขืจ 40 ืžื™ืœื™ืึธืŸ ืจื™ืงื•ื•ืขืก / ืžื™ืŸ.

ื”ืึทื’ื“ืึธืžืข

  • ื“ืขืจ ืึทืจื˜ื™ืงืœ ืื™ื– ื’ืขื•ื•ืขืŸ ื’ืขืฉืจื™ื‘ืŸ ืฆื• ื”ืขืœืคืŸ ืคึฟืึทืจืฉื˜ื™ื™ืŸ ื“ื™ ืคืึทื ื’ืงืฉืึทื ื™ื ื’ ืคื•ืŸ ื“ื™ ื™ / ืึธ ืจืขืึทืงื˜ืึธืจ, ืื•ืŸ ื“ืขืจื™ื‘ืขืจ ืคึฟืึทืจืฉื˜ื™ื™ืŸ ื“ื™ ืจื™ืกืงืก ื•ื•ืขืŸ ืื™ืจ ื ื•ืฆืŸ ืขืก.
  • ื•ื•ื™ืกืŸ ืคื•ืŸ ื“ื™ ื‘ืึทืกื™ืงืก ืื™ื– ืคืืจืœืื ื’ื˜ ืฆื• ืคึฟืึทืจืฉื˜ื™ื™ืŸ ื“ืขื ืึทืจื˜ื™ืงืœ. C ืฉืคึผืจืึทืš ืื•ืŸ ืขื˜ืœืขื›ืข ื“ืขืจืคืึทืจื•ื ื’ ืื™ืŸ ื ืขืฅ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ืึทื ื˜ื•ื•ื™ืงืœื•ื ื’.
  • ืึทืœืข ืงืึธื“ ืื™ื– ื’ืขืฉืจื™ื‘ืŸ ืื™ืŸ C ืฉืคึผืจืึทืš ืฉื˜ืจืขื ื’ ืœื•ื™ื˜ ืฆื• (ื•ื•ืึธืจืขื ืขืŸ: ืœืึทื ื’ ืคึผื“ืฃ) ืฆื• C11 ื ืึธืจืžืึทืœ ืคึฟืึทืจ ืœื™ื ื•ืงืก ืื•ืŸ ื‘ื ื™ืžืฆื ืื•ื™ืฃ ื’ื™ื˜ื”ื•ื‘.

ืคืืจื•ื•ืืก ืื™ื– ื“ืึธืก ื ื™ื™ื˜ื™ืง?

ืžื™ื˜ ื“ื™ ื’ืจืึธื•ื™ื ื’ ืคึผืึธืคึผื•ืœืึทืจื™ื˜ืขื˜ ืคื•ืŸ ื“ืขืจ ืื™ื ื˜ืขืจื ืขืฅ, ื•ื•ืขื‘ ืกืขืจื•ื•ืขืจืก ืื ื’ืขื”ื•ื™ื‘ืŸ ืฆื• ืฉืขืคึผืŸ ืึท ื’ืจื•ื™ืก ื ื•ืžืขืจ ืคื•ืŸ ืงืึทื ืขืงืฉืึทื ื– ืกื™ื™ืžืึทืœื˜ื™ื™ื ื™ืึทืกืœื™, ืื•ืŸ ื“ืขืจื™ื‘ืขืจ ืฆื•ื•ื™ื™ ืึทืคึผืจืึธื•ื˜ืฉื™ื– ื–ืขื ืขืŸ ื’ืขืคืจื•ื•ื•ื˜: ื‘ืœืึทืงื™ื ื’ I/O ืื•ื™ืฃ ืึท ื’ืจื•ื™ืก ื ื•ืžืขืจ ืคื•ืŸ ืึทืก ืคึฟืขื“ืขื ืื•ืŸ ื ื™ื˜-ื‘ืœืึทืงื™ื ื’ I/O ืื™ืŸ ืงืึธืžื‘ื™ื ืึทืฆื™ืข ืžื™ื˜ ืึท ื’ืขืฉืขืขื ื™ืฉ ืึธื ื–ืึธื’ ืกื™ืกื˜ืขื, ืื•ื™ืš ื’ืขืจื•ืคืŸ "ืกื™ืกื˜ืขื ืกืขืœืขืงื˜ืึธืจ" (ืขืคึผืึธืœ/kqueue/IOCP/ ืขื˜ืง).

ื“ืขืจ ืขืจืฉื˜ืขืจ ืฆื•ื’ืึทื ื’ ื™ื ื•ื•ืึทืœื•ื•ื“ ืงืจื™ื™ื™ื˜ื™ื ื’ ืึท ื ื™ื™ึท ืึทืก ืคืึธื“ืขื ืคึฟืึทืจ ื™ืขื“ืขืจ ื™ื ืงืึทืžื™ื ื’ ืงืฉืจ. ื–ื™ื™ึทืŸ ื›ื™ืกืึธืจืŸ ืื™ื– ื ืขื‘ืขืš ืกืงืึทืœืึทื‘ื™ืœื™ื˜ื™: ื“ื™ ืึธืคึผืขืจื™ื™ื˜ื™ื ื’ ืกื™ืกื˜ืขื ื•ื•ืขื˜ ื”ืึธื‘ืŸ ืฆื• ื™ื ืกื˜ืจื•ืžืขื ื˜ ืคื™ืœืข ืงืึธื ื˜ืขืงืกื˜ ื˜ืจืึทื ื–ื™ืฉืึทื ื– ะธ ืกื™ืกื˜ืขื ืจื•ืคื˜. ื–ื™ื™ ื–ืขื ืขืŸ ื˜ื™ื™ึทืขืจ ืึทืคึผืขืจื™ื™ืฉืึทื ื– ืื•ืŸ ืงืขื ืขืŸ ืคื™ืจืŸ ืฆื• ืึท ืคืขืœืŸ ืคื•ืŸ ืคืจื™ื™ ื‘ืึทืจืึทืŸ ืžื™ื˜ ืึท ื™ืžืคึผืจืขืกื™ื•ื• ื ื•ืžืขืจ ืคื•ืŸ ืงืึทื ืขืงืฉืึทื ื–.

ื“ื™ ืžืึทื“ืึทืคื™ื™ื“ ื•ื•ืขืจืกื™ืข ื›ื™ื™ืœื™ื™ืฅ ืคืึทืจืคืขืกื˜ื™ืงื˜ ื ื•ืžืขืจ ืคื•ืŸ ืคึฟืขื“ืขื (ืคืึธื“ืขื ื‘ืขืงืŸ), ื“ืขืจืžื™ื˜ ืคึผืจืขื•ื•ืขื ื˜ื™ื ื’ ื“ื™ ืกื™ืกื˜ืขื ืคื•ืŸ ืึทื‘ืึธืจื˜ื™ื ื’ ื“ื•ืจื›ืคื™ืจื•ื ื’, ืึธื‘ืขืจ ืื™ืŸ ื“ืขืจ ื–ืขืœื‘ื™ืงืขืจ ืฆื™ื™ื˜ ื™ื ื˜ืจืึธื•ื“ื•ืกื™ื ื’ ืึท ื ื™ื™ึทืข ืคึผืจืึธื‘ืœืขื: ืื•ื™ื‘ ืึท ืคืึธื“ืขื ื‘ืขืงืŸ ืื™ื– ืื™ืฆื˜ ืืคื’ืขืฉื˜ืขืœื˜ ื“ื•ืจืš ืœืึทื ื’ ืœื™ื™ืขื ืขืŸ ืึทืคึผืขืจื™ื™ืฉืึทื ื–, ืื ื“ืขืจืข ืกืึทืงืึทืฅ ื•ื•ืึธืก ื–ืขื ืขืŸ ืฉื•ื™ืŸ ื‘ื™ื›ื•ืœืช ืฆื• ื‘ืึทืงื•ืžืขืŸ ื“ืึทื˜ืŸ ืงืขื ืขืŸ ื ื™ืฉื˜ ื˜ืึธืŸ ืึทื–ื•ื™.

ื“ื™ ืจื’ืข ืฆื•ื’ืึทื ื’ ื ื™ืฆื˜ ื’ืขืฉืขืขื ื™ืฉ ืึธื ื–ืึธื’ ืกื™ืกื˜ืขื (ืกื™ืกื˜ืขื ืกืขืœืขืงื˜ืึธืจ) ืฆื•ื’ืขืฉื˜ืขืœื˜ ื“ื•ืจืš ื“ื™ ืึทืก. ื“ืขืจ ืึทืจื˜ื™ืงืœ ื“ื™ืกืงืึทืกื˜ ื“ื™ ืžืขืจืกื˜ ืคึผืจืึธืกื˜ ื˜ื™ืคึผ ืคื•ืŸ ืกื™ืกื˜ืขื ืกืขืœืขืงื˜ืึธืจ, ื‘ืื–ื™ืจื˜ ืื•ื™ืฃ ืึทืœืขืจืฅ (ื’ืขืฉืขืขื ื™ืฉืŸ, ื ืึธื•ื˜ืึทืคืึทืงื™ื™ืฉืึทื ื–) ื•ื•ืขื’ืŸ ื’ืจื™ื™ื˜ืงื™ื™ึทื˜ ืคึฟืึทืจ I/O ืึทืคึผืขืจื™ื™ืฉืึทื ื–, ืืœื ื•ื•ื™ ืื•ื™ืฃ ื ืึธื•ื˜ืึทืคืึทืงื™ื™ืฉืึทื ื– ื•ื•ืขื’ืŸ ื–ื™ื™ืขืจ ืงืึทืžืคึผืœื™ืฉืึทืŸ. ื ืกื™ืžืคึผืœืึทืคื™ื™ื“ ื‘ื™ื™ึทืฉืคึผื™ืœ ืคื•ืŸ ื–ื™ื™ึทืŸ ื ื•ืฆืŸ ืงืขื ืขืŸ ื–ื™ื™ืŸ ืจืขืคึผืจื™ื–ืขื ื˜ื™ื“ ื“ื•ืจืš ื“ื™ ืคืืœื’ืขื ื“ืข ื‘ืœืึธืง ื“ื™ืึทื’ืจืึทืžืข:

ื’ืึทื ืฅ-ืคื™ื˜ืฉืขืจื“ ื ืึทืงืขื˜-C I/O ืจืขืึทืงื˜ืึธืจ

ื“ืขืจ ื—ื™ืœื•ืง ืฆื•ื•ื™ืฉืŸ ื“ื™ ืึทืคึผืจืึธื•ื˜ืฉื™ื– ืื™ื– ื•ื•ื™ ื’ื™ื™ื˜:

  • ื‘ืœืึทืงื™ื ื’ ืื™ืš / ืึธ ืึทืคึผืขืจื™ื™ืฉืึทื ื– ืกื•ืกืคึผืขื ื“ื™ืจืŸ ื‘ืึทื ื™ืฆืขืจ ืœื•ื™ืคืŸ ื‘ื™ื–ื‘ื™ื– ื“ื™ ืึทืก ืื™ื– ืจืขื›ื˜ ื“ืขืคืจืึทื’ืžืึทื ืฅ ื™ื ืงืึทืžื™ื ื’ IP ืคึผืึทืงื™ืฅ ืฆื• ื‘ื™ื™ื˜ ืกื˜ืจื™ื (ื˜ืงืคึผ, ืจื™ืกื™ื•ื•ื™ื ื’ ื“ืึทื˜ืŸ) ืึธื“ืขืจ ืขืก ื•ื•ืขื˜ ื ื™ืฉื˜ ื–ื™ื™ืŸ ื’ืขื ื•ื’ ืคึผืœืึทืฅ ื‘ื ื™ืžืฆื ืื™ืŸ ื“ื™ ื™ื ืขืจืœืขืš ืฉืจื™ื™ึทื‘ืŸ ื‘ืึทืคืขืจื– ืคึฟืึทืจ ืกืึทื‘ืกืึทืงื•ื•ืึทื ื˜ ืฉื™ืงื˜ ื“ื•ืจืš ื ื™ืง (ืฉื™ืงื˜ ื“ืึทื˜ืŸ).
  • ืกื™ืกื˜ืขื ืกืขืœืขืงื˜ืึธืจ ืžื™ื˜ ื“ื™ ืฆื™ื™ื˜ ื ืึธื•ื˜ืึทืคื™ื™ื– ื“ื™ ืคึผืจืึธื’ืจืึทื ืึทื– ื“ื™ ืึทืก ืฉื•ื™ืŸ ื“ืขืคืจืึทื’ืžืขื ื˜ืขื“ IP ืคึผืึทืงื™ืฅ (ื˜ืงืคึผ, ื“ืึทื˜ืŸ ืึธืคึผื˜ืจืึธื’) ืึธื“ืขืจ ื’ืขื ื•ื’ ืคึผืœืึทืฅ ืื™ืŸ ื™ื ืขืจืœืขืš ืฉืจื™ื™ึทื‘ืŸ ื‘ืึทืคืขืจื– ืฉื•ื™ืŸ ื‘ื ื™ืžืฆื (ืฉื™ืงื˜ ื“ืึทื˜ืŸ).

ืฆื• ืกืึทื›ืึทืงืœ ืขืก ืึทืจื•ื™ืฃ, ืจื™ื–ืขืจื•ื•ื™ื ื’ ืึทืŸ ืึทืก ืคืึธื“ืขื ืคึฟืึทืจ ื™ืขื“ืขืจ ื™ / ืึธ ืื™ื– ืึท ื•ื•ื™ืกื˜ ืคื•ืŸ ืงืึทืžืคึผื™ื•ื˜ื™ื ื’ ืžืึทื›ื˜, ื•ื•ื™ื™ึทืœ ืื™ืŸ ืคืึทืงื˜, ื“ื™ ืคึฟืขื“ืขื ื˜ืึธืŸ ื ื™ื˜ ื ื•ืฆืŸ ื ื•ืฆื™ืง ืึทืจื‘ืขื˜ (ื“ืขืจื™ื‘ืขืจ ื“ื™ ื˜ืขืจืžื™ืŸ "ื“ื™ ื•ื•ื™ื™ื›ื•ื•ืืจื’ ื™ื‘ืขืจืจื™ื™ึทืก"). ื“ื™ ืกื™ืกื˜ืขื ืกืขืœืขืงื˜ืึธืจ ืกืึทืœื•ื•ื– ื“ืขื ืคึผืจืึธื‘ืœืขื, ืึทืœืึทื•ื™ื ื’ ื“ื™ ื‘ืึทื ื™ืฆืขืจ ืคึผืจืึธื’ืจืึทื ืฆื• ื ื•ืฆืŸ ืงืคึผื• ืจืขืกื•ืจืกืŸ ืคื™ืœ ืžืขืจ ืขืงืึทื ืึทืžื™ืงืœื™.

ืื™ืš / ืึธ ืจืขืึทืงื˜ืึธืจ ืžืึธื“ืขืœ

ื“ืขืจ I/O ืจืขืึทืงื˜ืึธืจ ืึทืงื˜ ื•ื•ื™ ืึท ืฉื™ื›ื˜ืข ืฆื•ื•ื™ืฉืŸ ื“ื™ ืกื™ืกื˜ืขื ืกืขืœืขืงื˜ืึธืจ ืื•ืŸ ื“ื™ ื‘ืึทื ื™ืฆืขืจ ืงืึธื“. ื“ืขืจ ืคึผืจื™ื ืฆื™ืคึผ ืคื•ืŸ ื–ื™ื™ึทืŸ ืึธืคึผืขืจืึทืฆื™ืข ืื™ื– ื“ื™ืกืงืจื™ื™ื‘ื“ ื“ื•ืจืš ื“ื™ ืคืืœื’ืขื ื“ืข ื‘ืœืึธืง ื“ื™ืึทื’ืจืึทืžืข:

ื’ืึทื ืฅ-ืคื™ื˜ืฉืขืจื“ ื ืึทืงืขื˜-C I/O ืจืขืึทืงื˜ืึธืจ

  • ืœืึธื–ืŸ ืžื™ืจ ื“ืขืจืžืึธื ืขืŸ ืื™ืจ ืึทื– ืึท ื’ืขืฉืขืขื ื™ืฉ ืื™ื– ืึท ืึธื ื–ืึธื’ ืึทื– ืึท ื–ื™ื›ืขืจ ื›ืึธืœืขืœ ืื™ื– ื‘ื™ื›ื•ืœืช ืฆื• ื“ื•ืจื›ืคื™ืจืŸ ืึท ื ื™ื˜-ื‘ืœืึทืงื™ื ื’ ื™ / ืึธ ืึธืคึผืขืจืึทืฆื™ืข.
  • ืึท ื’ืขืฉืขืขื ื™ืฉ ื”ืึทื ื“ืœืขืจ ืื™ื– ืึท ืคึฟื•ื ืงืฆื™ืข ื’ืขืจื•ืคึฟืŸ ื“ื•ืจืš ื“ื™ ื™ / ืึธ ืจืขืึทืงื˜ืึธืจ ื•ื•ืขืŸ ืึท ื’ืขืฉืขืขื ื™ืฉ ืื™ื– ื‘ืืงื•ืžืขืŸ, ื•ื•ืึธืก ื“ืขืžืึธืœื˜ ืคึผืขืจืคืึธืจืžื– ืึท ื ื™ื˜-ื‘ืœืึทืงื™ื ื’ ื™ / ืึธ ืึธืคึผืขืจืึทืฆื™ืข.

ืขืก ืื™ื– ื•ื•ื™ื›ื˜ื™ืง ืฆื• ื˜ืึธืŸ ืึทื– ื“ืขืจ I / O ืจืขืึทืงื˜ืึธืจ ืื™ื– ื“ื•ืจืš ื“ืขืคึฟื™ื ื™ืฆื™ืข ืื™ื™ืŸ-ื˜ืจืขื“ื™ื“, ืึธื‘ืขืจ ืขืก ืื™ื– ื’ืึธืจื ื™ืฉื˜ ืกื˜ืึธืคึผืคึผื™ื ื’ ื“ืขื ื‘ืึทื’ืจื™ืฃ ืฆื• ื–ื™ื™ืŸ ื’ืขื•ื•ื™ื™ื ื˜ ืื™ืŸ ืึท ืžืึทืœื˜ื™-ื˜ืจืขื“ื™ื“ ืกื•ื•ื™ื•ื•ืข ืื™ืŸ ืึท ืคืึทืจื”ืขืœื˜ืขื ื™ืฉ ืคื•ืŸ 1 ืคืึธื“ืขื: 1 ืจืขืึทืงื˜ืึธืจ, ื“ืขืจืžื™ื˜ ืจื™ืกื™ื™ืงืœื™ื ื’ ืึทืœืข ืงืคึผื• ืงืึธืจืขืก.

ื™ืžืคึผืœืขืžืขื ื˜ืึทื˜ื™ืึธืŸ

ืžื™ืจ ื•ื•ืขืœืŸ ืฉื˜ืขืœืŸ ื“ื™ ืฆื™ื‘ื•ืจ ืฆื•ื‘ื™ื ื“ ืื™ืŸ ืึท ื˜ืขืงืข reactor.h, ืื•ืŸ ื™ืžืคึผืœืึทืžืขื ื˜ื™ื™ืฉืึทืŸ - ืื™ืŸ reactor.c. reactor.h ื•ื•ืขื˜ ืฆื•ื ื•ื™ืคืฉื˜ืขืœื  ื–ื™ืš ืคื•ืŸ ื“ื™ ืคืืœื’ืขื ื“ืข ืžื•ื“ืขื•ืช:

ื•ื•ื™ื™ึทื–ืŸ ื“ืขืงืœืขืจื™ื™ืฉืึทื ื– ืื™ืŸ ืจืขืึทืงื˜ืึธืจ.ื”

typedef struct reactor Reactor;

/*
 * ะฃะบะฐะทะฐั‚ะตะปัŒ ะฝะฐ ั„ัƒะฝะบั†ะธัŽ, ะบะพั‚ะพั€ะฐั ะฑัƒะดะตั‚ ะฒั‹ะทั‹ะฒะฐั‚ัŒัั I/O ั€ะตะฐะบั‚ะพั€ะพะผ ะฟั€ะธ ะฟะพัั‚ัƒะฟะปะตะฝะธะธ
 * ัะพะฑั‹ั‚ะธั ะพั‚ ัะธัั‚ะตะผะฝะพะณะพ ัะตะปะตะบั‚ะพั€ะฐ.
 */
typedef void (*Callback)(void *arg, int fd, uint32_t events);

/*
 * ะ’ะพะทะฒั€ะฐั‰ะฐะตั‚ `NULL` ะฒ ัะปัƒั‡ะฐะต ะพัˆะธะฑะบะธ, ะฝะต-`NULL` ัƒะบะฐะทะฐั‚ะตะปัŒ ะฝะฐ `Reactor` ะฒ
 * ะฟั€ะพั‚ะธะฒะฝะพะผ ัะปัƒั‡ะฐะต.
 */
Reactor *reactor_new(void);

/*
 * ะžัะฒะพะฑะพะถะดะฐะตั‚ ัะธัั‚ะตะผะฝั‹ะน ัะตะปะตะบั‚ะพั€, ะฒัะต ะทะฐั€ะตะณะธัั‚ั€ะธั€ะพะฒะฐะฝะฝั‹ะต ัะพะบะตั‚ั‹ ะฒ ะดะฐะฝะฝั‹ะน ะผะพะผะตะฝั‚
 * ะฒั€ะตะผะตะฝะธ ะธ ัะฐะผ I/O ั€ะตะฐะบั‚ะพั€.
 *
 * ะกะปะตะดัƒัŽั‰ะธะต ั„ัƒะฝะบั†ะธะธ ะฒะพะทะฒั€ะฐั‰ะฐัŽั‚ -1 ะฒ ัะปัƒั‡ะฐะต ะพัˆะธะฑะบะธ, 0 ะฒ ัะปัƒั‡ะฐะต ัƒัะฟะตั…ะฐ.
 */
int reactor_destroy(Reactor *reactor);

int reactor_register(const Reactor *reactor, int fd, uint32_t interest,
                     Callback callback, void *callback_arg);
int reactor_deregister(const Reactor *reactor, int fd);
int reactor_reregister(const Reactor *reactor, int fd, uint32_t interest,
                       Callback callback, void *callback_arg);

/*
 * ะ—ะฐะฟัƒัะบะฐะตั‚ ั†ะธะบะป ัะพะฑั‹ั‚ะธะน ั ั‚ะฐะนะผ-ะฐัƒั‚ะพะผ `timeout`.
 *
 * ะญั‚ะฐ ั„ัƒะฝะบั†ะธั ะฟะตั€ะตะดะฐัั‚ ัƒะฟั€ะฐะฒะปะตะฝะธะต ะฒั‹ะทั‹ะฒะฐัŽั‰ะตะผัƒ ะบะพะดัƒ ะตัะปะธ ะพั‚ะฒะตะดั‘ะฝะฝะพะต ะฒั€ะตะผั ะฒั‹ัˆะปะพ
 * ะธะปะธ/ะธ ะฟั€ะธ ะพั‚ััƒั‚ัั‚ะฒะธะธ ะทะฐั€ะตะณะธัั‚ั€ะธั€ะพะฒะฐะฝะฝั‹ั… ัะพะบะตั‚ะพะฒ.
 */
int reactor_run(const Reactor *reactor, time_t timeout);

ื“ื™ I/O ืจืขืึทืงื˜ืึธืจ ืกื˜ืจื•ืงื˜ื•ืจ ื‘ืืฉื˜ื™ื™ื˜ ืคื•ืŸ ื˜ืขืงืข ื“ื™ืกืงืจื™ืคึผื˜ืึธืจ ืกืขืœืขืงื˜ืึธืจ ืขืคึผืึธืœ ะธ ื”ืึทืฉ ื˜ื™ืฉืŸ GHashTable, ื•ื•ืึธืก ืžืึทืคึผืก ื™ืขื“ืขืจ ื›ืึธืœืขืœ ืฆื• CallbackData (ืกื˜ืจื•ืงื˜ื•ืจ ืคื•ืŸ ืึท ื’ืขืฉืขืขื ื™ืฉ ื”ืึทื ื“ืœืขืจ ืื•ืŸ ืึท ื‘ืึทื ื™ืฆืขืจ ืึทืจื’ื•ืžืขื ื˜ ืคึฟืึทืจ ืขืก).

ื•ื•ื™ื™ึทื–ืŸ ืจืขืึทืงื˜ืึธืจ ืื•ืŸ ืงืึทืœืœื‘ืึทืงืงื“ืึทื˜ืึท

struct reactor {
    int epoll_fd;
    GHashTable *table; // (int, CallbackData)
};

typedef struct {
    Callback callback;
    void *arg;
} CallbackData;

ื‘ื™ื˜ืข ื˜ืึธืŸ ืึทื– ืžื™ืจ ื”ืึธื‘ืŸ ืขื ื™ื™ื‘ืึทืœื“ ื“ื™ ืคื™ื™ื™ืงื™ื™ื˜ ืฆื• ืฉืขืคึผืŸ ื“ืขืจืขื ื“ื™ืงื˜ ื˜ื™ืคึผ ืœื•ื™ื˜ ื“ืขื ืื™ื ื“ืขืงืก. ืื™ืŸ reactor.h ืžื™ืจ ื“ืขืจืงืœืขืจืŸ ื“ื™ ืกื˜ืจื•ืงื˜ื•ืจ reactorืื•ืŸ ืื™ืŸ reactor.c ืžื™ืจ ื“ืขืคื™ื ื™ืจืŸ ืขืก, ื“ืขืจืžื™ื˜ ืคึผืจืขื•ื•ืขื ื˜ื™ื ื’ ื“ืขืจ ื‘ืึทื ื™ืฆืขืจ ืคื•ืŸ ื‘ืคื™ืจื•ืฉ ื˜ืฉืึทื ื’ื™ื ื’ ื–ื™ื™ึทืŸ ืคืขืœื“ืขืจ. ื“ืึธืก ืื™ื– ืื™ื™ื ืขืจ ืคื•ืŸ ื“ื™ ืžืึธื“ืขืœืก ื›ื™ื™ื“ื™ื ื’ ื“ืึทื˜ืŸ, ื•ื•ืึธืก ืกืึทืงืกื™ื ืงื˜ืœื™ ืคื™ืฅ ืื™ืŸ C ืกืขืžืึทื ื˜ื™ืงืก.

ืคืึทื ื’ืงืฉืึทื ื– reactor_register, reactor_deregister ะธ reactor_reregister ื“ืขืจื”ื™ื™ึทื ื˜ื™ืงืŸ ื“ื™ ืจืฉื™ืžื” ืคื•ืŸ ืกืึทืงืึทืฅ ืคื•ืŸ ืื™ื ื˜ืขืจืขืก ืื•ืŸ ืงืึธืจืึทืกืคึผืึทื ื“ื™ื ื’ ื’ืขืฉืขืขื ื™ืฉ ื”ืึทื ื“ืœืขืจืก ืื™ืŸ ื“ื™ ืกื™ืกื˜ืขื ืกืขืœืขืงื˜ืึธืจ ืื•ืŸ ื”ืึทืฉ ื˜ื™ืฉ.

ื•ื•ื™ื™ึทื–ืŸ ืจืขื’ื™ืกื˜ืจืึทืฆื™ืข ืคืึทื ื’ืงืฉืึทื ื–

#define REACTOR_CTL(reactor, op, fd, interest)                                 
    if (epoll_ctl(reactor->epoll_fd, op, fd,                                   
                  &(struct epoll_event){.events = interest,                    
                                        .data = {.fd = fd}}) == -1) {          
        perror("epoll_ctl");                                                   
        return -1;                                                             
    }

int reactor_register(const Reactor *reactor, int fd, uint32_t interest,
                     Callback callback, void *callback_arg) {
    REACTOR_CTL(reactor, EPOLL_CTL_ADD, fd, interest)
    g_hash_table_insert(reactor->table, int_in_heap(fd),
                        callback_data_new(callback, callback_arg));
    return 0;
}

int reactor_deregister(const Reactor *reactor, int fd) {
    REACTOR_CTL(reactor, EPOLL_CTL_DEL, fd, 0)
    g_hash_table_remove(reactor->table, &fd);
    return 0;
}

int reactor_reregister(const Reactor *reactor, int fd, uint32_t interest,
                       Callback callback, void *callback_arg) {
    REACTOR_CTL(reactor, EPOLL_CTL_MOD, fd, interest)
    g_hash_table_insert(reactor->table, int_in_heap(fd),
                        callback_data_new(callback, callback_arg));
    return 0;
}

ื ืึธืš ื“ื™ I / O ืจืขืึทืงื˜ืึธืจ ื™ื ื˜ืขืจืกืขืคึผื˜ืึทื“ ื“ื™ ื’ืขืฉืขืขื ื™ืฉ ืžื™ื˜ ื“ื™ ื“ื™ืกืงืจื™ืคึผื˜ืึธืจ fd, ืขืก ืจื•ืคื˜ ื“ื™ ืงืึธืจืึทืกืคึผืึทื ื“ื™ื ื’ ื’ืขืฉืขืขื ื™ืฉ ื”ืึทื ื“ืœืขืจ, ืฆื• ื•ื•ืึธืก ืขืก ืคึผืึทืกื™ื– fd, ื‘ื™ืกืœ ืžืึทืกืงืข ื“ื–ืฉืขื ืขืจื™ื™ื˜ืึทื“ ื’ืขืฉืขืขื ื™ืฉืŸ ืื•ืŸ ืึท ื‘ืึทื ื™ืฆืขืจ ื˜ื™ื™ึทื˜ืœ ืฆื• void.

ื•ื•ื™ื™ึทื–ืŸ reactor_run () ืคึฟื•ื ืงืฆื™ืข

int reactor_run(const Reactor *reactor, time_t timeout) {
    int result;
    struct epoll_event *events;
    if ((events = calloc(MAX_EVENTS, sizeof(*events))) == NULL)
        abort();

    time_t start = time(NULL);

    while (true) {
        time_t passed = time(NULL) - start;
        int nfds =
            epoll_wait(reactor->epoll_fd, events, MAX_EVENTS, timeout - passed);

        switch (nfds) {
        // ะžัˆะธะฑะบะฐ
        case -1:
            perror("epoll_wait");
            result = -1;
            goto cleanup;
        // ะ’ั€ะตะผั ะฒั‹ัˆะปะพ
        case 0:
            result = 0;
            goto cleanup;
        // ะฃัะฟะตัˆะฝะฐั ะพะฟะตั€ะฐั†ะธั
        default:
            // ะ’ั‹ะทะฒะฐั‚ัŒ ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะพะฒ ัะพะฑั‹ั‚ะธะน
            for (int i = 0; i < nfds; i++) {
                int fd = events[i].data.fd;

                CallbackData *callback =
                    g_hash_table_lookup(reactor->table, &fd);
                callback->callback(callback->arg, fd, events[i].events);
            }
        }
    }

cleanup:
    free(events);
    return result;
}

ืฆื• ืกืึทืžืขืจื™ื™ื–, ื“ื™ ืงื™ื™ื˜ ืคื•ืŸ ืคืึทื ื’ืงืฉืึทื ื– ืงืึทืœืœืก ืื™ืŸ ื‘ืึทื ื™ืฆืขืจ ืงืึธื“ ื•ื•ืขื˜ ื ืขืžืขืŸ ื“ื™ ืคืืœื’ืขื ื“ืข ืคืึธืจืขื:

ื’ืึทื ืฅ-ืคื™ื˜ืฉืขืจื“ ื ืึทืงืขื˜-C I/O ืจืขืึทืงื˜ืึธืจ

ืื™ื™ืŸ ื˜ืจืขื“ื™ื“ ืกืขืจื•ื•ืขืจ

ืื™ืŸ ืกื“ืจ ืฆื• ืคึผืจื•ื‘ื™ืจืŸ ื“ื™ ื™ / ืึธ ืจืขืึทืงื˜ืึธืจ ืื•ื ื˜ืขืจ ื”ื•ื™ืš ืžืึทืกืข, ืžื™ืจ ื•ื•ืขืœืŸ ืฉืจื™ื™ึทื‘ืŸ ืึท ืคึผืฉื•ื˜ ื”ื˜ื˜ืคึผ ื•ื•ืขื‘ ืกืขืจื•ื•ืขืจ ื•ื•ืึธืก ืจื™ืกืคึผืึทื ื“ื– ืฆื• ืงื™ื™ืŸ ื‘ืงืฉื” ืžื™ื˜ ืึท ื‘ื™ืœื“.

ื ืฉื ืขืœ ืจืขืคึฟืขืจืขื ืฅ ืฆื• ื“ื™ ื”ื˜ื˜ืคึผ ืคึผืจืึธื˜ืึธืงืึธืœ

ื”ื˜ื˜ืคึผ - ื“ืึธืก ืื™ื– ื“ืขืจ ืคึผืจืึธื˜ืึธืงืึธืœ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ืžื“ืจื’ื”, ื‘ืคึฟืจื˜ ื’ืขื ื™ืฆื˜ ืคึฟืึทืจ ืกืขืจื•ื•ืขืจ-ื‘ืœืขื˜ืขืจืขืจ ื™ื ื˜ืขืจืึทืงืฉืึทืŸ.

ื”ื˜ื˜ืคึผ ืงืขื ืขืŸ ื–ื™ื™ืŸ ืœื™ื™ื›ื˜ ื’ืขื•ื•ื™ื™ื ื˜ ืื™ื‘ืขืจ ืึทืจื™ื‘ืขืจืคื™ืจืŸ ืคึผืจืึธื˜ืึธืงืึธืœ ื˜ืงืคึผ, ืฉื™ืงื˜ ืื•ืŸ ืจื™ืกื™ื•ื•ื™ื ื’ ืึทืจื˜ื™ืงืœืขืŸ ืื™ืŸ ืึท ืกืคึผืขืกื™ืคื™ืขื“ ืคึฟืึธืจืžืึทื˜ ืกืคึผืขืฆื™ืคื™ืงืึทืฆื™ืข.

ื‘ืขื˜ืŸ ืคึฟืึธืจืžืึทื˜

<ะšะžะœะะะ”ะ> <URI> <ะ’ะ•ะ ะกะ˜ะฏ HTTP>CRLF
<ะ—ะะ“ะžะ›ะžะ’ะžะš 1>CRLF
<ะ—ะะ“ะžะ›ะžะ’ะžะš 2>CRLF
<ะ—ะะ“ะžะ›ะžะ’ะžะš N>CRLF CRLF
<ะ”ะะะะซะ•>

  • CRLF ืื™ื– ืึท ืกื™ืงื•ื•ืึทื ืก ืคื•ืŸ ืฆื•ื•ื™ื™ ืื•ืชื™ื•ืช: r ะธ n, ืกืขืคึผืขืจื™ื™ื˜ื™ื ื’ ื“ื™ ืขืจืฉื˜ืขืจ ืฉื•ืจื” ืคื•ืŸ ื“ื™ ื‘ืขื˜ืŸ, ื›ืขื“ืขืจื– ืื•ืŸ ื“ืึทื˜ืŸ.
  • <ะšะžะœะะะ”ะ> - ืื™ื™ื ืขืจ ืคื•ืŸ CONNECT, DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT, TRACE. ื“ืขืจ ื‘ืœืขื˜ืขืจืขืจ ื•ื•ืขื˜ ืฉื™ืงืŸ ืึท ื‘ืึทืคึฟืขืœ ืฆื• ืื•ื ื“ื–ืขืจ ืกืขืจื•ื•ืขืจ GET, ื˜ื™ื™ึทื˜ืฉ "ืฉื™ืงืŸ ืžื™ืจ ื“ื™ ืื™ื ื”ืึทืœื˜ ืคื•ืŸ ื“ืขืจ ื˜ืขืงืข."
  • <URI> - ืžื•ื ื“ื™ืจ ืžื™ื˜ืœ ื™ื“ืขื ื˜ื™ืคื™ืขืจ. ืคึฟืึทืจ ื‘ื™ื™ึทืฉืคึผื™ืœ, ืื•ื™ื‘ URI = /index.html, ื“ืขืจ ืงืœื™ืขื ื˜ ืจื™ืงื•ื•ืขืก ื“ื™ ื”ื•ื™ืคึผื˜ ื‘ืœืึทื˜ ืคื•ืŸ ื“ืขื ืคึผืœืึทืฅ.
  • <ะ’ะ•ะ ะกะ˜ะฏ HTTP> - ื•ื•ืขืจืกื™ืข ืคื•ืŸ โ€‹โ€‹โ€‹โ€‹ื”ื˜ื˜ืคึผ ืคึผืจืึธื˜ืึธืงืึธืœ ืื™ืŸ ื“ืขื ืคึฟืึธืจืžืึทื˜ HTTP/X.Y. ื“ื™ ืžืขืจืกื˜ ืงืึทืžืึทื ืœื™ ื’ืขื ื™ืฆื˜ ื•ื•ืขืจืกื™ืข ื”ื™ื™ึทื ื˜ ืื™ื– HTTP/1.1.
  • <ะ—ะะ“ะžะ›ะžะ’ะžะš N> ืื™ื– ืึท ืฉืœื™ืกืœ-ื•ื•ืขืจื˜ ืคึผืึธืจ ืื™ืŸ ื“ืขื ืคึฟืึธืจืžืึทื˜ <ะšะ›ะฎะง>: <ะ—ะะะงะ•ะะ˜ะ•>, ื’ืขืฉื™ืงื˜ ืฆื• ื“ื™ ืกืขืจื•ื•ืขืจ ืคึฟืึทืจ ื•ื•ื™ื™ึทื˜ืขืจ ืึทื ืึทืœื™ืกื™ืก.
  • <ะ”ะะะะซะ•> - ื“ืึทื˜ืŸ ืคืืจืœืื ื’ื˜ ื“ื•ืจืš ื“ื™ ืกืขืจื•ื•ืขืจ ืฆื• ื“ื•ืจื›ืคื™ืจืŸ ื“ื™ ืึธืคึผืขืจืึทืฆื™ืข. ืึธืคื˜ ืขืก ืื™ื– ืคึผืฉื•ื˜ ื“ื–ืฉืกืึธืŸ ืึธื“ืขืจ ืงื™ื™ืŸ ืื ื“ืขืจืข ืคึฟืึธืจืžืึทื˜.

ืขื ื˜ืคืขืจ ืคึฟืึธืจืžืึทื˜

<ะ’ะ•ะ ะกะ˜ะฏ HTTP> <ะšะžะ” ะกะขะะขะฃะกะ> <ะžะŸะ˜ะกะะะ˜ะ• ะกะขะะขะฃะกะ>CRLF
<ะ—ะะ“ะžะ›ะžะ’ะžะš 1>CRLF
<ะ—ะะ“ะžะ›ะžะ’ะžะš 2>CRLF
<ะ—ะะ“ะžะ›ะžะ’ะžะš N>CRLF CRLF
<ะ”ะะะะซะ•>

  • <ะšะžะ” ะกะขะะขะฃะกะ> ืื™ื– ืึท ื ื•ืžืขืจ ื•ื•ืึธืก ืจืขืคึผืจืึทื–ืขื ืฅ ื“ื™ ืจืขื–ื•ืœื˜ืึทื˜ ืคื•ืŸ ื“ื™ ืึธืคึผืขืจืึทืฆื™ืข. ืื•ื ื“ื–ืขืจ ืกืขืจื•ื•ืขืจ ื•ื•ืขื˜ ืฉื˜ืขื ื“ื™ืง ืฆื•ืจื™ืงืงื•ืžืขืŸ ืกื˜ืึทื˜ื•ืก 200 (ืžืฆืœื™ื— ืึธืคึผืขืจืึทืฆื™ืข).
  • <ะžะŸะ˜ะกะะะ˜ะ• ะกะขะะขะฃะกะ> - ืฉื˜ืจื™ืงืœ ืคืึทืจื˜ืจืขื˜ื•ื ื’ ืคื•ืŸ ื“ื™ ืกื˜ืึทื˜ื•ืก ืงืึธื“. ืคึฟืึทืจ ืกื˜ืึทื˜ื•ืก ืงืึธื“ 200 ื“ืึธืก ืื™ื– OK.
  • <ะ—ะะ“ะžะ›ะžะ’ะžะš N> - ื›ืขื“ืขืจ ืคื•ืŸ ื“ืขืจ ื–ืขืœื‘ื™ืงืขืจ ืคึฟืึธืจืžืึทื˜ ื•ื•ื™ ืื™ืŸ ื“ื™ ื‘ืงืฉื”. ืžื™ืจ ื•ื•ืขืœืŸ ืฆื•ืจื™ืงืงื•ืžืขืŸ ื“ื™ ื˜ื™ื˜ืœืขืŸ Content-Length (ื˜ืขืงืข ื’ืจื™ื™ืก) ืื•ืŸ Content-Type: text/html (ืฆื•ืจื™ืงืงื•ืžืขืŸ ื“ืึทื˜ืŸ ื˜ื™ืคึผ).
  • <ะ”ะะะะซะ•> - ื“ืึทื˜ืŸ ื’ืขื‘ืขื˜ืŸ ื“ื•ืจืš ื“ืขืจ ื‘ืึทื ื™ืฆืขืจ. ืื™ืŸ ืื•ื ื“ื–ืขืจ ืคืึทืœ, ื“ืึธืก ืื™ื– ื“ืขืจ ื•ื•ืขื’ ืฆื• ื“ื™ ื‘ื™ืœื“ ืื™ืŸ HTML.

ื˜ืขืงืข http_server.c (ืื™ื™ืŸ ื˜ืจืขื“ื™ื“ ืกืขืจื•ื•ืขืจ) ื›ื•ืœืœ ื˜ืขืงืข common.h, ื•ื•ืึธืก ื›ึผื•ืœืœ ื“ื™ ืคืืœื’ืขื ื“ืข ืคื•ื ืงืฆื™ืข ืคึผืจืึธื•ื˜ืึทื˜ื™ื™ืคึผืก:

ื•ื•ื™ื™ึทื–ืŸ ืคึฟื•ื ืงืฆื™ืข ืคึผืจืึธื•ื˜ืึทื˜ื™ื™ืคึผืก ืื™ืŸ ืคึผืจืึธืกื˜.ื”

/*
 * ะžะฑั€ะฐะฑะพั‚ั‡ะธะบ ัะพะฑั‹ั‚ะธะน, ะบะพั‚ะพั€ั‹ะน ะฒั‹ะทะพะฒะตั‚ัั ะฟะพัะปะต ั‚ะพะณะพ, ะบะฐะบ ัะพะบะตั‚ ะฑัƒะดะตั‚
 * ะณะพั‚ะพะฒ ะฟั€ะธะฝัั‚ัŒ ะฝะพะฒะพะต ัะพะตะดะธะฝะตะฝะธะต.
 */
static void on_accept(void *arg, int fd, uint32_t events);

/*
 * ะžะฑั€ะฐะฑะพั‚ั‡ะธะบ ัะพะฑั‹ั‚ะธะน, ะบะพั‚ะพั€ั‹ะน ะฒั‹ะทะพะฒะตั‚ัั ะฟะพัะปะต ั‚ะพะณะพ, ะบะฐะบ ัะพะบะตั‚ ะฑัƒะดะตั‚
 * ะณะพั‚ะพะฒ ะพั‚ะฟั€ะฐะฒะธั‚ัŒ HTTP ะพั‚ะฒะตั‚.
 */
static void on_send(void *arg, int fd, uint32_t events);

/*
 * ะžะฑั€ะฐะฑะพั‚ั‡ะธะบ ัะพะฑั‹ั‚ะธะน, ะบะพั‚ะพั€ั‹ะน ะฒั‹ะทะพะฒะตั‚ัั ะฟะพัะปะต ั‚ะพะณะพ, ะบะฐะบ ัะพะบะตั‚ ะฑัƒะดะตั‚
 * ะณะพั‚ะพะฒ ะฟั€ะธะฝัั‚ัŒ ั‡ะฐัั‚ัŒ HTTP ะทะฐะฟั€ะพัะฐ.
 */
static void on_recv(void *arg, int fd, uint32_t events);

/*
 * ะŸะตั€ะตะฒะพะดะธั‚ ะฒั…ะพะดัั‰ะตะต ัะพะตะดะธะฝะตะฝะธะต ะฒ ะฝะตะฑะปะพะบะธั€ัƒัŽั‰ะธะน ั€ะตะถะธะผ.
 */
static void set_nonblocking(int fd);

/*
 * ะŸะตั‡ะฐั‚ะฐะตั‚ ะฟะตั€ะตะดะฐะฝะฝั‹ะต ะฐั€ะณัƒะผะตะฝั‚ั‹ ะฒ stderr ะธ ะฒั‹ั…ะพะดะธั‚ ะธะท ะฟั€ะพั†ะตััะฐ ั
 * ะบะพะดะพะผ `EXIT_FAILURE`.
 */
static noreturn void fail(const char *format, ...);

/*
 * ะ’ะพะทะฒั€ะฐั‰ะฐะตั‚ ั„ะฐะนะปะพะฒั‹ะน ะดะตัะบั€ะธะฟั‚ะพั€ ัะพะบะตั‚ะฐ, ัะฟะพัะพะฑะฝะพะณะพ ะฟั€ะธะฝะธะผะฐั‚ัŒ ะฝะพะฒั‹ะต
 * TCP ัะพะตะดะธะฝะตะฝะธั.
 */
static int new_server(bool reuse_port);

ื“ื™ ืคืึทื ื’ืงืฉืึทื ืึทืœ ืžืึทืงืจืึธื• ืื™ื– ืื•ื™ืš ื“ื™ืกืงืจื™ื™ื‘ื“ SAFE_CALL() ืื•ืŸ ื“ื™ ืคึฟื•ื ืงืฆื™ืข ืื™ื– ื“ื™ืคื™ื™ื ื“ fail(). ื“ืขืจ ืžืึทืงืจืึธื• ืงืึทืžืคึผืขืจื– ื“ื™ ื•ื•ืขืจื˜ ืคื•ืŸ ื“ื™ ืื•ื™ืกื“ืจื•ืง ืžื™ื˜ ื“ืขืจ ื˜ืขื•ืช, ืื•ืŸ ืื•ื™ื‘ ื“ื™ ืฆื•ืฉื˜ืึทื ื“ ืื™ื– ืืžืช, ืจื•ืคื˜ ื“ื™ ืคึฟื•ื ืงืฆื™ืข fail():

#define SAFE_CALL(call, error)                                                 
    do {                                                                       
        if ((call) == error) {                                                   
            fail("%s", #call);                                                 
        }                                                                      
    } while (false)

ืคื•ื ืงืฆื™ืึธื ื™ืจืŸ fail() ืคึผืจื™ื ืฅ ื“ื™ ื“ื•ืจื›ื’ืขื’ืื ื’ืขืŸ ืึทืจื’ื•ืžืขื ื˜ืŸ ืฆื• ื“ื™ ื•ื•ืึธืงื–ืึทืœ (ื•ื•ื™ printf()) ืื•ืŸ ื˜ืขืจืžืึทื ื™ื™ืฅ ื“ื™ ืคึผืจืึธื’ืจืึทื ืžื™ื˜ ื“ื™ ืงืึธื“ EXIT_FAILURE:

static noreturn void fail(const char *format, ...) {
    va_list args;
    va_start(args, format);
    vfprintf(stderr, format, args);
    va_end(args);
    fprintf(stderr, ": %sn", strerror(errno));
    exit(EXIT_FAILURE);
}

ืคื•ื ืงืฆื™ืึธื ื™ืจืŸ new_server() ืงืขืจื˜ ื“ื™ ื˜ืขืงืข ื“ื™ืกืงืจื™ืคึผื˜ืึธืจ ืคื•ืŸ ื“ื™ "ืกืขืจื•ื•ืขืจ" ื›ืึธืœืขืœ ื‘ืืฉืืคืŸ ื“ื•ืจืš ืกื™ืกื˜ืขื ืงืึทืœืœืก socket(), bind() ะธ listen() ืื•ืŸ ืงืขื ืขืŸ ืฆื• ืึธื ื ืขืžืขืŸ ื™ื ืงืึทืžื™ื ื’ ืงืึทื ืขืงืฉืึทื ื– ืื™ืŸ ืึท ื ื™ื˜-ื‘ืœืึทืงื™ื ื’ ืžืึธื“ืข.

ื•ื•ื™ื™ึทื–ืŸ new_server() ืคึฟื•ื ืงืฆื™ืข

static int new_server(bool reuse_port) {
    int fd;
    SAFE_CALL((fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP)),
              -1);

    if (reuse_port) {
        SAFE_CALL(
            setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &(int){1}, sizeof(int)),
            -1);
    }

    struct sockaddr_in addr = {.sin_family = AF_INET,
                               .sin_port = htons(SERVER_PORT),
                               .sin_addr = {.s_addr = inet_addr(SERVER_IPV4)},
                               .sin_zero = {0}};

    SAFE_CALL(bind(fd, (struct sockaddr *)&addr, sizeof(addr)), -1);
    SAFE_CALL(listen(fd, SERVER_BACKLOG), -1);
    return fd;
}

  • ื‘ืึทืžืขืจืงื•ื ื’ ืึทื– ื“ื™ ื›ืึธืœืขืœ ืื™ื– ื˜ื›ื™ืœืขืก ื‘ืืฉืืคืŸ ืื™ืŸ ื ื™ื˜-ื‘ืœืึทืงื™ื ื’ ืžืึธื“ืข ื ื™ืฆืŸ ื“ื™ ืคืึธืŸ SOCK_NONBLOCKืึทื–ื•ื™ ืึทื– ืื™ืŸ ื“ื™ ืคึฟื•ื ืงืฆื™ืข on_accept() (ืœื™ื™ืขื ืขืŸ ืžืขืจ) ืกื™ืกื˜ืขื ืจื•ืคืŸ accept() ื”ืื˜ ื ื™ืฉื˜ ืึธืคึผื’ืขืฉื˜ืขืœื˜ ื“ื™ ืคืึธื“ืขื ื“ื•ืจื›ืคื™ืจื•ื ื’.
  • ืฆื™ reuse_port ืื™ื– ื’ืœื™ื™ืš ืฆื• true, ื“ืขืžืึธืœื˜ ื“ืขื ืคึฟื•ื ืงืฆื™ืข ื•ื•ืขื˜ ืงืึทื ืคื™ื’ื™ืขืจ ื“ื™ ื›ืึธืœืขืœ ืžื™ื˜ ื“ื™ ืึธืคึผืฆื™ืข SO_REUSEPORT ื“ื•ืจืš setsockopt()ืฆื• ื ื•ืฆืŸ ื“ื™ ื–ืขืœื‘ืข ืคึผืึธืจื˜ ืื™ืŸ ืึท ืžื•ืœื˜ื™-ื˜ืจืขื“ื™ื“ ืกื•ื•ื™ื•ื•ืข (ื–ืขืŸ ืึธืคึผื˜ื™ื™ืœื•ื ื’ "ืžื•ืœื˜ื™-ื˜ืจืขื“ื™ื“ ืกืขืจื•ื•ืขืจ").

ื’ืขืฉืขืขื ื™ืฉ ื”ืึทื ื“ืœืขืจ on_accept() ื’ืขืจื•ืคึฟืŸ ื ืึธืš ื“ื™ ืึทืก ื“ื–ืฉืขื ืขืจื™ื™ืฅ ืึท ื’ืขืฉืขืขื ื™ืฉ EPOLLIN, ืื™ืŸ ื“ืขื ืคืึทืœ ื˜ื™ื™ึทื˜ืฉ ืึทื– ื“ื™ ื ื™ื™ึทืข ืงืฉืจ ืงืขื ืขืŸ ื–ื™ื™ืŸ ืื ื’ืขื ื•ืžืขืŸ. on_accept() ืึทืงืกืขืคึผืฅ ืึท ื ื™ื™ึทืข ืงืฉืจ, ืกื•ื•ื™ื˜ืฉื™ื– ืขืก ืฆื• ื ื™ื˜-ื‘ืœืึทืงื™ื ื’ ืžืึธื“ืข ืื•ืŸ ืจืขื“ื–ืฉื™ืกื˜ืขืจื– ืžื™ื˜ ืึท ื’ืขืฉืขืขื ื™ืฉ ื”ืึทื ื“ืœืขืจ on_recv() ืื™ืŸ ืึทืŸ I/O ืจืขืึทืงื˜ืึธืจ.

ื•ื•ื™ื™ึทื–ืŸ on_accept () ืคึฟื•ื ืงืฆื™ืข

static void on_accept(void *arg, int fd, uint32_t events) {
    int incoming_conn;
    SAFE_CALL((incoming_conn = accept(fd, NULL, NULL)), -1);
    set_nonblocking(incoming_conn);
    SAFE_CALL(reactor_register(reactor, incoming_conn, EPOLLIN, on_recv,
                               request_buffer_new()),
              -1);
}

ื’ืขืฉืขืขื ื™ืฉ ื”ืึทื ื“ืœืขืจ on_recv() ื’ืขืจื•ืคึฟืŸ ื ืึธืš ื“ื™ ืึทืก ื“ื–ืฉืขื ืขืจื™ื™ืฅ ืึท ื’ืขืฉืขืขื ื™ืฉ EPOLLIN, ืื™ืŸ ื“ืขื ืคืึทืœ ื˜ื™ื™ึทื˜ืฉ ืึทื– ื“ื™ ืงืฉืจ ืจืขื’ื™ืกื˜ืจื™ืจื˜ on_accept(), ื’ืจื™ื™ื˜ ืฆื• ื‘ืึทืงื•ืžืขืŸ ื“ืึทื˜ืŸ.

on_recv() ืœื™ื™ืขื ื˜ ื“ืึทื˜ืŸ ืคื•ืŸ ื“ื™ ืงืฉืจ ื‘ื™ื– ื“ื™ ื”ื˜ื˜ืคึผ ื‘ืขื˜ืŸ ืื™ื– ื’ืึธืจ ื‘ืืงื•ืžืขืŸ, ืื•ืŸ ืขืก ืจืขื“ื–ืฉื™ืกื˜ืขืจื– ืึท ื”ืึทื ื“ืœืขืจ on_send() ืฆื• ืฉื™ืงืŸ ืึท ื”ื˜ื˜ืคึผ ืขื ื˜ืคืขืจ. ืื•ื™ื‘ ื“ืขืจ ืงืœื™ืขื ื˜ ื‘ืจื™ื™ืงืก ื“ื™ ืงืฉืจ, ื“ื™ ื›ืึธืœืขืœ ืื™ื– ื“ืขืจืขื’ื™ืกื˜ืจื™ืจื˜ ืื•ืŸ ืคึฟืึทืจืžืึทื›ื˜ ื ื™ืฆืŸ close().

ื•ื•ื™ื™ึทื–ืŸ ืคึฟื•ื ืงืฆื™ืข on_recv ()

static void on_recv(void *arg, int fd, uint32_t events) {
    RequestBuffer *buffer = arg;

    // ะŸั€ะธะฝะธะผะฐะตะผ ะฒั…ะพะดะฝั‹ะต ะดะฐะฝะฝั‹ะต ะดะพ ั‚ะตั… ะฟะพั€, ั‡ั‚ะพ recv ะฒะพะทะฒั€ะฐั‚ะธั‚ 0 ะธะปะธ ะพัˆะธะฑะบัƒ
    ssize_t nread;
    while ((nread = recv(fd, buffer->data + buffer->size,
                         REQUEST_BUFFER_CAPACITY - buffer->size, 0)) > 0)
        buffer->size += nread;

    // ะšะปะธะตะฝั‚ ะพะฑะพั€ะฒะฐะป ัะพะตะดะธะฝะตะฝะธะต
    if (nread == 0) {
        SAFE_CALL(reactor_deregister(reactor, fd), -1);
        SAFE_CALL(close(fd), -1);
        request_buffer_destroy(buffer);
        return;
    }

    // read ะฒะตั€ะฝัƒะป ะพัˆะธะฑะบัƒ, ะพั‚ะปะธั‡ะฝัƒัŽ ะพั‚ ะพัˆะธะฑะบะธ, ะฟั€ะธ ะบะพั‚ะพั€ะพะน ะฒั‹ะทะพะฒ ะทะฐะฑะปะพะบะธั€ัƒะตั‚
    // ะฟะพั‚ะพะบ
    if (errno != EAGAIN && errno != EWOULDBLOCK) {
        request_buffer_destroy(buffer);
        fail("read");
    }

    // ะŸะพะปัƒั‡ะตะฝ ะฟะพะปะฝั‹ะน HTTP ะทะฐะฟั€ะพั ะพั‚ ะบะปะธะตะฝั‚ะฐ. ะขะตะฟะตั€ัŒ ั€ะตะณะธัั‚ั€ะธั€ัƒะตะผ ะพะฑั€ะฐะฑะพั‚ั‡ะธะบะฐ
    // ัะพะฑั‹ั‚ะธะน ะดะปั ะพั‚ะฟั€ะฐะฒะบะธ ะดะฐะฝะฝั‹ั…
    if (request_buffer_is_complete(buffer)) {
        request_buffer_clear(buffer);
        SAFE_CALL(reactor_reregister(reactor, fd, EPOLLOUT, on_send, buffer),
                  -1);
    }
}

ื’ืขืฉืขืขื ื™ืฉ ื”ืึทื ื“ืœืขืจ on_send() ื’ืขืจื•ืคึฟืŸ ื ืึธืš ื“ื™ ืึทืก ื“ื–ืฉืขื ืขืจื™ื™ืฅ ืึท ื’ืขืฉืขืขื ื™ืฉ EPOLLOUT, ื˜ื™ื™ึทื˜ืฉ ืึทื– ื“ื™ ืงืฉืจ ืจืขื’ื™ืกื˜ืจื™ืจื˜ on_recv(), ื’ืจื™ื™ื˜ ืฆื• ืฉื™ืงืŸ ื“ืึทื˜ืŸ. ื“ื™ ืคึฟื•ื ืงืฆื™ืข ืกืขื ื“ื– ืึท ื”ื˜ื˜ืคึผ ืขื ื˜ืคืขืจ ืžื™ื˜ HTML ืžื™ื˜ ืึท ื‘ื™ืœื“ ืฆื• ื“ืขื ืงืœื™ืขื ื˜ ืื•ืŸ ื“ืขืžืึธืœื˜ ืขื ื“ืขืจื•ื ื’ืขืŸ ื“ื™ ื’ืขืฉืขืขื ื™ืฉ ื”ืึทื ื“ืœืขืจ ืฆื•ืจื™ืง ืฆื• on_recv().

ื•ื•ื™ื™ึทื–ืŸ on_send () ืคึฟื•ื ืงืฆื™ืข

static void on_send(void *arg, int fd, uint32_t events) {
    const char *content = "<img "
                          "src="https://habrastorage.org/webt/oh/wl/23/"
                          "ohwl23va3b-dioerobq_mbx4xaw.jpeg">";
    char response[1024];
    sprintf(response,
            "HTTP/1.1 200 OK" CRLF "Content-Length: %zd" CRLF "Content-Type: "
            "text/html" DOUBLE_CRLF "%s",
            strlen(content), content);

    SAFE_CALL(send(fd, response, strlen(response), 0), -1);
    SAFE_CALL(reactor_reregister(reactor, fd, EPOLLIN, on_recv, arg), -1);
}

ืื•ืŸ ืœืขืกืึธืฃ, ืื™ืŸ ื“ืขืจ ื˜ืขืงืข http_server.c, ืื™ืŸ ืคึฟื•ื ืงืฆื™ืข main() ืžื™ืจ ืฉืึทืคึฟืŸ ืึทืŸ ืื™ืš / ืึธ ืจืขืึทืงื˜ืึธืจ ื ื™ืฆืŸ reactor_new(), ืฉืึทืคึฟืŸ ืึท ืกืขืจื•ื•ืขืจ ื›ืึธืœืขืœ ืื•ืŸ ืคืึทืจืฉืจื™ื™ึทื‘ืŸ ืขืก, ืึธื ื”ื™ื™ื‘ ื“ืขื ืจืขืึทืงื˜ืึธืจ ื ื™ืฆืŸ reactor_run() ืคึฟืึทืจ ืคึผื•ื ืงื˜ ืื™ื™ืŸ ืžื™ื ื•ื˜, ืื•ืŸ ื“ืขืžืึธืœื˜ ืžื™ืจ ืžืขืœื“ื•ื ื’ ืจืขืกื•ืจืกืŸ ืื•ืŸ ืึทืจื•ื™ืกื’ืึทื ื’ ื“ืขื ืคึผืจืึธื’ืจืึทื.

ื•ื•ื™ื™ึทื–ืŸ http_server.c

#include "reactor.h"

static Reactor *reactor;

#include "common.h"

int main(void) {
    SAFE_CALL((reactor = reactor_new()), NULL);
    SAFE_CALL(
        reactor_register(reactor, new_server(false), EPOLLIN, on_accept, NULL),
        -1);
    SAFE_CALL(reactor_run(reactor, SERVER_TIMEOUT_MILLIS), -1);
    SAFE_CALL(reactor_destroy(reactor), -1);
}

ืœืึธืžื™ืจ ืงืึธื ื˜ืจืึธืœื™ืจืŸ ืึทื– ืึทืœืฅ ืึทืจื‘ืขื˜ ื•ื•ื™ ื“ืขืจื•ื•ืึทืจื˜. ืงืึทืžืคึผื™ื™ืœื™ื ื’ (chmod a+x compile.sh && ./compile.sh ืื™ืŸ ื“ื™ ืคึผืจื•ื™ืขืงื˜ ื•ื•ืึธืจืฆืœ) ืื•ืŸ ืงืึทื˜ืขืจ ื“ื™ ื–ื™ืš-ื’ืขืฉืจื™ื‘ืŸ ืกืขืจื•ื•ืขืจ, ืขืคืขื ืขืŸ http://127.0.0.1:18470 ืื™ืŸ ื“ืขื ื‘ืœืขื˜ืขืจืขืจ ืื•ืŸ ื–ืขืŸ ื•ื•ืึธืก ืžื™ืจ ื“ืขืจื•ื•ืึทืจื˜:

ื’ืึทื ืฅ-ืคื™ื˜ืฉืขืจื“ ื ืึทืงืขื˜-C I/O ืจืขืึทืงื˜ืึธืจ

ืคืึธืจืฉื˜ืขืœื•ื ื’ ืžืขื–ืฉืขืจืžืึทื ื˜

ื•ื•ื™ื™ึทื–ืŸ ืžื™ื™ืŸ ืžืึทืฉื™ืŸ ืกืคึผืขืกืึทืคืึทืงื™ื™ืฉืึทื ื–

$ screenfetch
 MMMMMMMMMMMMMMMMMMMMMMMMMmds+.        OS: Mint 19.1 tessa
 MMm----::-://////////////oymNMd+`     Kernel: x86_64 Linux 4.15.0-20-generic
 MMd      /++                -sNMd:    Uptime: 2h 34m
 MMNso/`  dMM    `.::-. .-::.` .hMN:   Packages: 2217
 ddddMMh  dMM   :hNMNMNhNMNMNh: `NMm   Shell: bash 4.4.20
     NMm  dMM  .NMN/-+MMM+-/NMN` dMM   Resolution: 1920x1080
     NMm  dMM  -MMm  `MMM   dMM. dMM   DE: Cinnamon 4.0.10
     NMm  dMM  -MMm  `MMM   dMM. dMM   WM: Muffin
     NMm  dMM  .mmd  `mmm   yMM. dMM   WM Theme: Mint-Y-Dark (Mint-Y)
     NMm  dMM`  ..`   ...   ydm. dMM   GTK Theme: Mint-Y [GTK2/3]
     hMM- +MMd/-------...-:sdds  dMM   Icon Theme: Mint-Y
     -NMm- :hNMNNNmdddddddddy/`  dMM   Font: Noto Sans 9
      -dMNs-``-::::-------.``    dMM   CPU: Intel Core i7-6700 @ 8x 4GHz [52.0ยฐC]
       `/dMNmy+/:-------------:/yMMM   GPU: NV136
          ./ydNMMMMMMMMMMMMMMMMMMMMM   RAM: 2544MiB / 7926MiB
             .MMMMMMMMMMMMMMMMMMM

ื–ืืœ ืก ืžืขืกื˜ืŸ ื“ื™ ืคืึธืจืฉื˜ืขืœื•ื ื’ ืคื•ืŸ ืึท ืื™ื™ืŸ-ื˜ืจืขื“ื™ื“ ืกืขืจื•ื•ืขืจ. ืœืืžื™ืจ ืขืคืขื ืขืŸ ืฆื•ื•ื™ื™ ื˜ืขืจืžื™ื ืืœืŸ: ืื™ืŸ ืื™ื™ื ืขื ื•ื•ืขืœืŸ ืžื™ืจ ืœื•ื™ืคืŸ ./http_server, ืื™ืŸ ืืŸ ืื ื“ืขืจ - wrk. ื ืึธืš ืึท ืžื™ื ื•ื˜, ื“ื™ ืคืืœื’ืขื ื“ืข ืกื˜ืึทื˜ื™ืกื˜ื™ืง ื•ื•ืขื˜ ื–ื™ื™ืŸ ื’ืขื•ื•ื™ื–ืŸ ืื™ืŸ ื“ื™ ืจื’ืข ื•ื•ืึธืงื–ืึทืœ:

$ wrk -c100 -d1m -t8 http://127.0.0.1:18470 -H "Host: 127.0.0.1:18470" -H "Accept-Language: en-US,en;q=0.5" -H "Connection: keep-alive"
Running 1m test @ http://127.0.0.1:18470
  8 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   493.52us   76.70us  17.31ms   89.57%
    Req/Sec    24.37k     1.81k   29.34k    68.13%
  11657769 requests in 1.00m, 1.60GB read
Requests/sec: 193974.70
Transfer/sec:     27.19MB

ืื•ื ื“ื–ืขืจ ืื™ื™ืŸ-ื˜ืจืขื“ื™ื“ ืกืขืจื•ื•ืขืจ ืื™ื– ื‘ื™ื›ื•ืœืช ืฆื• ืคึผืจืึธืฆืขืก ืื™ื‘ืขืจ 11 ืžื™ืœื™ืึธืŸ ืจื™ืงื•ื•ืขืก ืคึผืขืจ ืžื™ื ื•ื˜ ืขืจื™ื“ื–ืฉืึทื ื™ื™ื˜ืึทื“ ืคึฟื•ืŸ 100 ืงืึทื ืขืงืฉืึทื ื–. ื ื™ื˜ ืึท ืฉืœืขื›ื˜ ืจืขื–ื•ืœื˜ืึทื˜, ืึธื‘ืขืจ ืงืขื ืขืŸ ืขืก ื–ื™ื™ืŸ ื™ืžืคึผืจื•ื•ื•ื“?

ืžื•ืœื˜ื™ื˜ื”ืจืขืึทื“ืขื“ ืกืขืจื•ื•ืขืจ

ื•ื•ื™ ื“ืขืจืžืื ื˜ ืื•ื™ื‘ืŸ, ื“ื™ I/O ืจืขืึทืงื˜ืึธืจ ืงืขื ืขืŸ ื–ื™ื™ืŸ ื‘ืืฉืืคืŸ ืื™ืŸ ื‘ืึทื–ื•ื ื“ืขืจ ืคึฟืขื“ืขื, ืื•ืŸ ื“ืขืจืžื™ื˜ ื ื™ืฆืŸ ืึทืœืข ืงืคึผื• ืงืึธืจืขืก. ื–ืืœ ืก ืฉื˜ืขืœืŸ ื“ืขื ืฆื•ื’ืึทื ื’ ืื™ืŸ ืคื™ืจ:

ื•ื•ื™ื™ึทื–ืŸ http_server_multithreaded.c

#include "reactor.h"

static Reactor *reactor;
#pragma omp threadprivate(reactor)

#include "common.h"

int main(void) {
#pragma omp parallel
    {
        SAFE_CALL((reactor = reactor_new()), NULL);
        SAFE_CALL(reactor_register(reactor, new_server(true), EPOLLIN,
                                   on_accept, NULL),
                  -1);
        SAFE_CALL(reactor_run(reactor, SERVER_TIMEOUT_MILLIS), -1);
        SAFE_CALL(reactor_destroy(reactor), -1);
    }
}

ืื™ืฆื˜ ื™ืขื“ืขืจ ืคืึธื“ืขื ืคืืจืžืื’ื˜ ื–ืฒืŸ ืืฒื’ืขื ืขื ืจืขืึทืงื˜ืึธืจ:

static Reactor *reactor;
#pragma omp threadprivate(reactor)

ื‘ื™ื˜ืข ื˜ืึธืŸ ืึทื– ื“ื™ ืคึฟื•ื ืงืฆื™ืข ืึทืจื’ื•ืžืขื ื˜ new_server() ืื“ื•ื•ืืงืื˜ืŸ true. ื“ืขื ืžื™ื˜ืœ ืึทื– ืžื™ืจ ื‘ืึทืฉื˜ื™ืžืขืŸ ื“ื™ ืึธืคึผืฆื™ืข ืฆื• ื“ื™ ืกืขืจื•ื•ืขืจ ื›ืึธืœืขืœ SO_REUSEPORTืฆื• ื ื•ืฆืŸ ืขืก ืื™ืŸ ืึท ืžืึทืœื˜ื™-ื˜ืจืขื“ื™ื“ ืกื•ื•ื™ื•ื•ืข. ืื™ืจ ืงืขื ืขืŸ ืœื™ื™ืขื ืขืŸ ืžืขืจ ื“ืขื˜ืึทื™ืœืก ื“ืึธ.

ืฆื•ื•ื™ื™ื˜ืข ืœื•ื™ืคืŸ

ืื™ืฆื˜ ืœืึธื–ืŸ ืื•ื ื“ื– ืžืขืกื˜ืŸ ื“ื™ ืคืึธืจืฉื˜ืขืœื•ื ื’ ืคื•ืŸ ืึท ืžื•ืœื˜ื™-ื˜ืจืขื“ื™ื“ ืกืขืจื•ื•ืขืจ:

$ wrk -c100 -d1m -t8 http://127.0.0.1:18470 -H "Host: 127.0.0.1:18470" -H "Accept-Language: en-US,en;q=0.5" -H "Connection: keep-alive"
Running 1m test @ http://127.0.0.1:18470
  8 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.14ms    2.53ms  40.73ms   89.98%
    Req/Sec    79.98k    18.07k  154.64k    78.65%
  38208400 requests in 1.00m, 5.23GB read
Requests/sec: 635876.41
Transfer/sec:     89.14MB

ื“ื™ ื ื•ืžืขืจ ืคื•ืŸ ืจื™ืงื•ื•ืขืก ืคึผืจืึทืกืขืกื˜ ืื™ืŸ 1 ืžื™ื ื•ื˜ ืื™ื– ื’ืขื•ื•ืืงืกืŸ ืžื™ื˜ ~3.28 ืžืืœ! ืึธื‘ืขืจ ืžื™ืจ ื”ืึธื‘ืŸ ื‘ืœื•ื™ื– ~ XNUMX ืžื™ืœื™ืึธืŸ ืงื•ืจืฅ ืคื•ืŸ ื“ื™ ืงื™ื™ึทืœืขื›ื™ืง ื ื•ืžืขืจ, ืึทื–ื•ื™ ืœืึธื–ืŸ ืื•ื ื“ื– ืคึผืจื•ื‘ื™ืจืŸ ืฆื• ืคืึทืจืจื™ื›ื˜ืŸ ื“ืึธืก.

ืขืจืฉื˜ืขืจ ืœืึธื–ืŸ ืก ืงื•ืง ืื™ืŸ ื“ื™ ืกื˜ืึทื˜ื™ืกื˜ื™ืง ื“ื–ืฉืขื ืขืจื™ื™ื˜ืึทื“ ื’ืื ืฅ:

$ sudo perf stat -B -e task-clock,context-switches,cpu-migrations,page-faults,cycles,instructions,branches,branch-misses,cache-misses ./http_server_multithreaded

 Performance counter stats for './http_server_multithreaded':

     242446,314933      task-clock (msec)         #    4,000 CPUs utilized          
         1โ€ฏ813โ€ฏ074      context-switches          #    0,007 M/sec                  
             4โ€ฏ689      cpu-migrations            #    0,019 K/sec                  
               254      page-faults               #    0,001 K/sec                  
   895โ€ฏ324โ€ฏ830โ€ฏ170      cycles                    #    3,693 GHz                    
   621โ€ฏ378โ€ฏ066โ€ฏ808      instructions              #    0,69  insn per cycle         
   119โ€ฏ926โ€ฏ709โ€ฏ370      branches                  #  494,653 M/sec                  
     3โ€ฏ227โ€ฏ095โ€ฏ669      branch-misses             #    2,69% of all branches        
           808โ€ฏ664      cache-misses                                                

      60,604330670 seconds time elapsed

ื ื™ืฆืŸ CPU Affinity, ื–ืึทืžืœื•ื ื’ ืžื™ื˜ -march=native, PGO, ืึท ืคืึทืจื’ืจืขืกืขืจืŸ ืื™ืŸ ื“ื™ ื ื•ืžืขืจ ืคื•ืŸ ื”ื™ืฅ ื’ืขืœื˜, ื”ืขื›ืขืจื•ื ื’ MAX_EVENTS ืื•ืŸ ื ื•ืฆืŸ EPOLLET ื”ืื˜ ื ื™ืฉื˜ ื’ืขื‘ืŸ ืึท ื‘ืึทื˜ื™ื™ึทื˜ื™ืง ืคืึทืจื’ืจืขืกืขืจืŸ ืื™ืŸ ืคืึธืจืฉื˜ืขืœื•ื ื’. ืึธื‘ืขืจ ื•ื•ืึธืก ื›ืึทืคึผืึทื ื– ืื•ื™ื‘ ืื™ืจ ืคืึทืจื’ืจืขืกืขืจืŸ ื“ื™ ื ื•ืžืขืจ ืคื•ืŸ ืกื™ื™ืžืึทืœื˜ื™ื™ื ื™ืึทืก ืงืึทื ืขืงืฉืึทื ื–?

ืกื˜ืึทื˜ื™ืกื˜ื™ืง ืคึฟืึทืจ 352 ืกื™ื™ืžืึทืœื˜ื™ื™ื ื™ืึทืก ืงืึทื ืขืงืฉืึทื ื–:

$ wrk -c352 -d1m -t8 http://127.0.0.1:18470 -H "Host: 127.0.0.1:18470" -H "Accept-Language: en-US,en;q=0.5" -H "Connection: keep-alive"
Running 1m test @ http://127.0.0.1:18470
  8 threads and 352 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     2.12ms    3.79ms  68.23ms   87.49%
    Req/Sec    83.78k    12.69k  169.81k    83.59%
  40006142 requests in 1.00m, 5.48GB read
Requests/sec: 665789.26
Transfer/sec:     93.34MB

ื“ืขืจ ื’ืขื•ื•ืืœื˜ ืจืขื–ื•ืœื˜ืึทื˜ ืื™ื– ื’ืขื•ื•ืขืŸ ื‘ืืงื•ืžืขืŸ, ืื•ืŸ ืžื™ื˜ ืื™ื ืึท ื˜ืฉื™ืงืึทื•ื•ืข ื’ืจืึทืคื™ืง ื•ื•ื™ื™ึทื–ื•ื ื’ ื“ื™ ืึธืคืขื ื’ื™ืงื™ื™ึทื˜ ืคื•ืŸ ื“ื™ ื ื•ืžืขืจ ืคื•ืŸ ืคึผืจืึทืกืขืกื˜ ืจื™ืงื•ื•ืขืก ืื™ืŸ 1 ืžื™ื ื•ื˜ ืื•ื™ืฃ ื“ื™ ื ื•ืžืขืจ ืคื•ืŸ ืงืึทื ืขืงืฉืึทื ื–:

ื’ืึทื ืฅ-ืคื™ื˜ืฉืขืจื“ ื ืึทืงืขื˜-C I/O ืจืขืึทืงื˜ืึธืจ

ืžื™ืจ ื–ืขืŸ ืึทื– ื ืึธืš ืึท ืคึผืึธืจ ืคื•ืŸ ื”ื•ื ื“ืขืจื˜ ืงืึทื ืขืงืฉืึทื ื–, ื“ื™ ื ื•ืžืขืจ ืคื•ืŸ ืคึผืจืึทืกืขืกื˜ ืจื™ืงื•ื•ืขืก ืคึฟืึทืจ ื‘ื™ื™ื“ืข ืกืขืจื•ื•ืขืจืก ืคืึทืœืŸ ืฉืืจืฃ (ืื™ืŸ ื“ื™ ืžื•ืœื˜ื™-ื˜ืจืขื“ื™ื“ ื•ื•ืขืจืกื™ืข ื“ืึธืก ืื™ื– ืžืขืจ ื‘ืืžืขืจืงื˜). ืื™ื– ื“ืึธืก ืฉื™ื™ึทื›ื•ืช ืฆื• ื“ื™ ื™ืžืคึผืœืึทืžืขื ื˜ื™ื™ืฉืึทืŸ ืคื•ืŸ Linux TCP / IP ืึธื ืœื™ื™ื’ืŸ? ืคื™ืœืŸ ืคืจื™ื™ ืฆื• ืฉืจื™ื™ึทื‘ืŸ ื“ื™ื™ืŸ ืึทืกืึทืžืคึผืฉืึทื ื– ื•ื•ืขื’ืŸ ื“ืขื ื ืึทื˜ื•ืจ ืคื•ืŸ ื“ื™ ื’ืจืึทืคื™ืง ืื•ืŸ ืึธืคึผื˜ื™ืžื™ื–ืึทื˜ื™ืึธื ืก ืคึฟืึทืจ ืžื•ืœื˜ื™-ื˜ืจืขื“ื™ื“ ืื•ืŸ ืื™ื™ืŸ-ื˜ืจืขื“ืขื“ ืึธืคึผืฆื™ืขืก ืื™ืŸ ื“ื™ ื‘ืึทืžืขืจืงื•ื ื’ืขืŸ.

ื•ื•ื™ ื‘ืืžืขืจืงื˜ ืื™ืŸ ื“ื™ ื‘ืึทืžืขืจืงื•ื ื’ืขืŸ, ื“ืขื ืคืึธืจืฉื˜ืขืœื•ื ื’ ืคึผืจื•ื‘ื™ืจืŸ ื˜ื•ื˜ ื ื™ืฉื˜ ื•ื•ื™ื™ึทื–ืŸ ื“ื™ ื ืึทื˜ื•ืจ ืคื•ืŸ ื“ื™ I / O ืจืขืึทืงื˜ืึธืจ ืื•ื ื˜ืขืจ ืคืึทืงื˜ื™ืฉ ืœืึธื•ื“ื–, ื•ื•ื™ื™ึทืœ ื›ึผืžืขื˜ ืฉื˜ืขื ื“ื™ืง ื“ืขืจ ืกืขืจื•ื•ืขืจ ื™ื ื˜ืขืจืึทืงืฅ ืžื™ื˜ ื“ื™ ื“ืึทื˜ืึทื‘ื™ื™ืก, ืึทื•ื˜ืคึผื•ืฅ ืœืึธื’ืก, ื ื™ืฆื˜ ืงืจื™ืคึผื˜ืึธื’ืจืึทืคื™ ืžื™ื˜ ื˜ืœืก ื•ื›ื“ื•', ื•ื•ื™ ืึท ืจืขื–ื•ืœื˜ืึทื˜ ืคื•ืŸ ื•ื•ืึธืก ื“ื™ ืžืึทืกืข ื•ื•ืขืจื˜ ื ื™ื˜-ืžื•ื ื“ื™ืจ (ื“ื™ื ืึทืžื™ืฉ). ื˜ืขืกืฅ ืฆื•ื–ืึทืžืขืŸ ืžื™ื˜ ื“ืจื™ื˜-ืคึผืึทืจื˜ื™ื™ ืงืึทืžืคึผืึธื•ื ืึทื ืฅ ื•ื•ืขื˜ ื–ื™ื™ืŸ ื“ื•ืจื›ื’ืขืงืึธื›ื˜ ืื™ืŸ ื“ืขื ืึทืจื˜ื™ืงืœ ื•ื•ืขื’ืŸ ื“ื™ ื™ / ืึธ ืคึผืจืึธืึทืงื˜ืึธืจ.

ื“ื™ืกืึทื“ื•ื•ืึทื ื˜ื™ื“ื–ืฉื™ื– ืคื•ืŸ ืื™ืš / ืึธ ืจืขืึทืงื˜ืึธืจ

ืื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ืคึฟืึทืจืฉื˜ื™ื™ืŸ ืึทื– ื“ื™ I / O ืจืขืึทืงื˜ืึธืจ ืื™ื– ื ื™ืฉื˜ ืึธืŸ ื–ื™ื™ืŸ ื“ื™ืกืึทื“ื•ื•ืึทื ื˜ื™ื“ื–ืฉื™ื–, ื ื™ื™ืžืœื™:

  • ื ื™ืฆืŸ ืึทืŸ ืื™ืš / ืึธ ืจืขืึทืงื˜ืึธืจ ืื™ืŸ ืึท ืžืึทืœื˜ื™-ื˜ืจืขื“ื™ื“ ืกื•ื•ื™ื•ื•ืข ืื™ื– ืขืคึผืขืก ืžืขืจ ืฉื•ื•ืขืจ, ื•ื•ื™ื™ึทืœ ืื™ืจ ื•ื•ืขื˜ ื”ืึธื‘ืŸ ืฆื• ืžืึทื ื™ื•ืึทืœื™ ืคื™ืจืŸ ื“ื™ ืคืœืึธื•ื–.
  • ืคื™ืจ ื•ื•ื™ื™ื–ื˜ ืึทื– ืื™ืŸ ืจื•ื‘ึฟ ืคืืœืŸ ื“ื™ ืžืึทืกืข ืื™ื– ื ื™ื˜-ืžื•ื ื“ื™ืจ, ื•ื•ืึธืก ืงืขื ืขืŸ ืคื™ืจืŸ ืฆื• ืื™ื™ืŸ ืคืึธื“ืขื ืœืึธื’ื™ื ื’ ื‘ืฉืขืช ืื ื“ืขืจืŸ ืื™ื– ืคืึทืจื ื•ืžืขืŸ ืžื™ื˜ ืึทืจื‘ืขื˜.
  • ืื•ื™ื‘ ืื™ื™ื ืขืจ ื’ืขืฉืขืขื ื™ืฉ ื”ืึทื ื“ืœืขืจ ื‘ืœืึทืงืก ืึท ืคืึธื“ืขื, ื“ืขืจ ืกื™ืกื˜ืขื ืกืขืœืขืงื˜ืึธืจ ื–ื™ืš ื•ื•ืขื˜ ืื•ื™ืš ืคืึทืจืฉืคึผืึทืจืŸ, ื•ื•ืึธืก ืงืขื ืขืŸ ืคื™ืจืŸ ืฆื• ืฉื•ื•ืขืจ-ืฆื•-ื’ืขืคื™ื ืขืŸ ื‘ืึทื’ื–.

ืกืึทืœื•ื•ื– ื“ื™ ืคึผืจืึธื‘ืœืขืžืก ืื™ืš / ืึธ ืคึผืจืึธืึทืงื˜ืึธืจ, ื•ื•ืึธืก ืึธืคื˜ ื”ืื˜ ืึท ืกืงืขื“ื–ืฉื•ืœืขืจ ืึทื– ื™ื•ื•ืึทื ืœื™ ื“ื™ืกื˜ืจื™ื‘ื™ื•ืฅ ื“ื™ ืžืึทืกืข ืฆื• ืึท ื‘ืขืงืŸ ืคื•ืŸ ืคึฟืขื“ืขื, ืื•ืŸ ืื•ื™ืš ื”ืื˜ ืึท ืžืขืจ ื‘ืึทืงื•ื•ืขื ืึทืคึผื™. ืžื™ืจ ื•ื•ืขืœืŸ ืจืขื“ืŸ ื•ื•ืขื’ืŸ ืื™ื ืฉืคึผืขื˜ืขืจ, ืื™ืŸ ืžื™ื™ืŸ ืื ื“ืขืจืข ืึทืจื˜ื™ืงืœ.

ืกืึธืฃ

ื“ืึธืก ืื™ื– ื•ื•ื• ืื•ื ื“ื–ืขืจ ื ืกื™ืขื” ืคื•ืŸ ื˜ืขืึธืจื™ืข ื’ืœื™ื™ืš ืื™ืŸ ื“ื™ ืคึผืจืึธืคื™ืœืขืจ ื•ื™ืกืžืึทื˜ืขืจืŸ ื”ืื˜ ืงื•ืžืขืŸ ืฆื• ืึท ืกื•ืฃ.

ืื™ืจ ื–ืึธืœ ื ื™ืฉื˜ ื•ื•ื•ื™ื ืขืŸ ืื•ื™ืฃ ื“ืขื, ื•ื•ื™ื™ึทืœ ืขืก ื–ืขื ืขืŸ ืคื™ืœืข ืื ื“ืขืจืข ื’ืœื™ื™ึทืš ื˜ืฉื™ืงืึทื•ื•ืข ืึทืคึผืจืึธื•ื˜ืฉื™ื– ืฆื• ืฉืจื™ื™ื‘ืŸ ื ืขืฅ ื•ื•ื™ื™ื›ื•ื•ืืจื’ ืžื™ื˜ ืคืึทืจืฉื™ื“ืขื ืข ืœืขื•ื•ืขืœืก ืคื•ืŸ ืงืึทื ื•ื•ื™ื ื™ืึทื ืก ืื•ืŸ ื’ื™ื›ืงื™ื™ึทื˜. ื˜ืฉื™ืงืึทื•ื•ืข, ืื™ืŸ ืžื™ื™ืŸ ืžื™ื™ื ื•ื ื’, ืœื™ื ืงืก ื–ืขื ืขืŸ ื’ืขื’ืขื‘ืŸ ืื•ื ื˜ืŸ.

ื‘ื™ื– ื•ื•ื™ื™ึทื˜ืขืจ ืฆื™ื™ึทื˜!

ื˜ืฉื™ืงืึทื•ื•ืข ืคืจืื™ืขืงื˜ืŸ

ื•ื•ืึธืก ืึทื ื“ืขืจืฉ ืฆื• ืœื™ื™ืขื ืขืŸ?

ืžืงื•ืจ: www.habr.com

ืœื™ื™ื’ืŸ ืึท ื‘ืึทืžืขืจืงื•ื ื’