เป€เบ•เบปเบฒเบ›เบฐเบ•เบดเบเบญเบ™ C I/O เป€เบ›เบปเปˆเบฒเบกเบตเบ„เบธเบ™เบชเบปเบกเบšเบฑเบ”เป€เบ•เบฑเบกเบฎเบนเบšเปเบšเบš

เป€เบ•เบปเบฒเบ›เบฐเบ•เบดเบเบญเบ™ C I/O เป€เบ›เบปเปˆเบฒเบกเบตเบ„เบธเบ™เบชเบปเบกเบšเบฑเบ”เป€เบ•เบฑเบกเบฎเบนเบšเปเบšเบš

เบเบฒเบ™เบ™เปเบฒเบชเบฐเป€เบซเบ™เบต

เป€เบ•เบปเบฒเบ›เบฐเบ•เบดเบเบญเบ™ I/O (เบชเบฒเบเบ”เบฝเบง เบงเบปเบ‡เป€เบซเบ”เบเบฒเบ™) เป€เบ›เบฑเบ™โ€‹เบฎเบนเบšโ€‹เปเบšเบšโ€‹เบชเปเบฒโ€‹เบฅเบฑเบšโ€‹เบเบฒเบ™โ€‹เบ‚เบฝเบ™โ€‹เบŠเบญเบšโ€‹เปเบงโ€‹เป‚เบซเบผเบ”โ€‹เบชเบนเบ‡โ€‹, เบ™เปเบฒโ€‹เปƒเบŠเป‰โ€‹เปƒเบ™โ€‹เบงเบดโ€‹เบ—เบตโ€‹เปเบเป‰โ€‹เป„เบ‚โ€‹เบ—เบตเปˆโ€‹เบ™เบดโ€‹เบเบปเบกโ€‹เบซเบผเบฒเบโ€‹:

เปƒเบ™เบšเบปเบ”เบ„เบงเบฒเบกเบ™เบตเป‰, เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเป€เบšเบดเปˆเบ‡ ins เปเบฅเบฐ outs เบ‚เบญเบ‡เป€เบ„เบทเปˆเบญเบ‡เบ›เบฐเบ•เบดเบเบญเบ™ I / O เปเบฅเบฐเบงเบดเบ—เบตเบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบ, เบ‚เบฝเบ™เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เปƒเบ™เบฅเบฐเบซเบฑเบ”เบซเบ™เป‰เบญเบเบเบงเปˆเบฒ 200 เป€เบชเบฑเป‰เบ™, เปเบฅเบฐเป€เบฎเบฑเบ”เปƒเบซเป‰เบ‚เบฐเบšเบงเบ™เบเบฒเบ™ HTTP server เบ‡เปˆเบฒเบเบ”เบฒเบเบซเบผเบฒเบเบเบงเปˆเบฒ 40 เบฅเป‰เบฒเบ™เบ„เปเบฒเบฎเป‰เบญเบ‡เบ‚เป / เบ™เบฒเบ—เบต.

เบ„เปเบฒเบญเบฐเบ—เบดเบ–เบฒเบ™

  • เบšเบปเบ”เบ„เบงเบฒเบกเบ–เบทเบเบ‚เบฝเบ™เป€เบžเบทเปˆเบญเบŠเปˆเบงเบเปƒเบซเป‰เป€เบ‚เบปเป‰เบฒเปƒเบˆเป€เบ–เบดเบ‡เบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบเบ‚เบญเบ‡เป€เบ„เบทเปˆเบญเบ‡เบ›เบฐเบ•เบดเบเบญเบ™ I/O, เปเบฅเบฐเบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบˆเบดเปˆเบ‡เป€เบ‚เบปเป‰เบฒเปƒเบˆเบ„เบงเบฒเบกเบชเปˆเบฝเบ‡เปƒเบ™เป€เบงเบฅเบฒเบ—เบตเปˆเปƒเบŠเป‰เบกเบฑเบ™.
  • เบ„เบงเบฒเบกเบฎเบนเป‰เบžเบทเป‰เบ™เบ–เบฒเบ™เปเบกเปˆเบ™เบˆเปเบฒเป€เบ›เบฑเบ™เป€เบžเบทเปˆเบญเป€เบ‚เบปเป‰เบฒเปƒเบˆเบšเบปเบ”เบ„เบงเบฒเบก. เบžเบฒเบชเบฒ C เปเบฅเบฐเบ›เบฐเบชเบปเบšเบเบฒเบ™เบšเบฒเบ‡เบขเปˆเบฒเบ‡เปƒเบ™เบเบฒเบ™เบžเบฑเบ”เบ—เบฐเบ™เบฒเปเบญเบฑเบšเบžเบฅเบดเป€เบ„เบŠเบฑเบ™เป€เบ„เบทเบญเบ‚เปˆเบฒเบ.
  • เบฅเบฐโ€‹เบซเบฑเบ”โ€‹เบ—เบฑเบ‡โ€‹เบซเบกเบปเบ”โ€‹เปเบกเปˆเบ™โ€‹เบ‚เบฝเบ™โ€‹เป€เบ›เบฑเบ™โ€‹เบžเบฒโ€‹เบชเบฒ C เบขเปˆเบฒเบ‡โ€‹เป€เบ‚เบฑเป‰เบกโ€‹เบ‡เบงเบ”โ€‹เบญเบตเบ‡โ€‹เบ•เบฒเบก (เบ‚เปเป‰เบ„เบงเบ™เบฅเบฐเบงเบฑเบ‡: PDF เบเบฒเบง) เบเบฑเบšเบกเบฒเบ”เบ•เบฐเบ–เบฒเบ™ C11 เบชเปเบฒเบฅเบฑเบš Linux เปเบฅเบฐเบกเบตเบขเบนเปˆเปƒเบ™ GitHub.

เป€เบ›เบฑเบ™เบซเบเบฑเบ‡เบˆเบถเปˆเบ‡เบˆเปเบฒเป€เบ›เบฑเบ™?

เบ”เป‰เบงเบเบ„เบงเบฒเบกเบ™เบดเบเบปเบกเบ‚เบญเบ‡เบญเบดเบ™เป€เบ•เบตเป€เบ™เบฑเบ”เบ—เบตเปˆเป€เบžเบตเปˆเบกเบ‚เบถเป‰เบ™, เป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบเป€เบงเบฑเบšเป€เบฅเบตเปˆเบกเบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡เบˆเบฑเบ”เบเบฒเบ™เบเบฑเบšเบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเบˆเปเบฒเบ™เบงเบ™เบซเบฅเบฒเบเบžเป‰เบญเบกเป†เบเบฑเบ™, เปเบฅเบฐเบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบชเบญเบ‡เบงเบดเบ—เบตเป„เบ”เป‰เบ–เบทเบเบžเบฐเบเบฒเบเบฒเบก: เบเบฒเบ™เบชเบฐเบเบฑเบ” I / O เปƒเบ™เบˆเปเบฒเบ™เบงเบ™เบซเบฅเบฒเบเบ‚เบญเบ‡ OS threads เปเบฅเบฐ I / O เบ—เบตเปˆเบšเปเปˆเบ›เบดเบ”เบเบฑเป‰เบ™เบ›เบฐเบชเบปเบกเบ›เบฐเบชเบฒเบ™เบเบฑเบš. เบฅเบฐเบšเบปเบšเบเบฒเบ™เปเบˆเป‰เบ‡เป€เบ•เบทเบญเบ™เป€เบซเบ”เบเบฒเบ™, เป€เบญเบตเป‰เบ™เบงเปˆเบฒ "เบ•เบปเบงเป€เบฅเบทเบญเบเบฅเบฐเบšเบปเบš" (epol/เบ„เบดเบง/IOCP/etc).

เบงเบดเบ—เบตเบเบฒเบ™เบ—เปเบฒเบญเบดเบ”เบเปˆเบฝเบงเบ‚เป‰เบญเบ‡เบเบฑเบšเบเบฒเบ™เบชเป‰เบฒเบ‡เบเบฐเบ—เบนเป‰ OS เปƒเบซเบกเปˆเบชเปเบฒเบฅเบฑเบšเปเบ•เปˆเบฅเบฐเบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเบ‚เบฒเป€เบ‚เบปเป‰เบฒ. เบ‚เปเป‰เป€เบชเบเบ‚เบญเบ‡เบกเบฑเบ™เปเบกเปˆเบ™เบเบฒเบ™เบ›เบฑเบšเบ‚เบฐเบซเบ™เบฒเบ”เบ—เบตเปˆเบšเปเปˆเบ”เบต: เบฅเบฐเบšเบปเบšเบ›เบฐเบ•เบดเบšเบฑเบ”เบเบฒเบ™เบˆเบฐเบ•เป‰เบญเบ‡เบ›เบฐเบ•เบดเบšเบฑเบ”เบซเบผเบฒเบเบขเปˆเบฒเบ‡ เบเบฒเบ™เบซเบฑเบ™เบ›เปˆเบฝเบ™เบชเบฐเบžเบฒเบšเบเบฒเบ™ ะธ เป‚เบ—เบฅเบฐเบšเบปเบš. เบžเบงเบเป€เบ‚เบปเบฒเป€เบ›เบฑเบ™เบเบฒเบ™เบ”เปเบฒเป€เบ™เบตเบ™เบ‡เบฒเบ™เบฅเบฒเบ„เบฒเปเบžเบ‡เปเบฅเบฐเบชเบฒเบกเบฒเบ”เบ™เปเบฒเป„เบ›เบชเบนเปˆเบเบฒเบ™เบ‚เบฒเบ” RAM เบŸเบฃเบตเบ—เบตเปˆเบกเบตเบˆเปเบฒเบ™เบงเบ™เบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเบ—เบตเปˆเบซเบ™เป‰เบฒเบ›เบฐเบ—เบฑเบšเปƒเบˆ.

เบชเบฐเบšเบฑเบšเบ”เบฑเบ”เปเบเป‰เป„เบ”เป‰เป€เบ™เบฑเป‰เบ™เปƒเบชเปˆ เบˆเปเบฒเบ™เบงเบ™เบ„เบปเบ‡เบ—เบตเปˆเบ‚เบญเบ‡เบเบฐเบ—เบนเป‰ (thread pool), เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบเบฒเบ™เบ›เป‰เบญเบ‡เบเบฑเบ™เบฅเบฐเบšเบปเบšเบˆเบฒเบเบเบฒเบ™เบเบปเบเป€เบฅเบตเบเบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”, เปเบ•เปˆเปƒเบ™เป€เบงเบฅเบฒเบ”เบฝเบงเบเบฑเบ™เปเบ™เบฐเบ™เปเบฒเบšเบฑเบ™เบซเบฒเปƒเบซเบกเปˆ: เบ–เป‰เบฒ thread pool เบ›เบฐเบˆเบธเบšเบฑเบ™เบ–เบทเบเบšเบฅเบฑเบญเบเป‚เบ”เบเบเบฒเบ™เบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™เบญเปˆเบฒเบ™เบเบฒเบง, เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™ socket เบญเบทเปˆเบ™เป†เบ—เบตเปˆเบกเบตเปเบฅเป‰เบงเบชเบฒเบกเบฒเบ”เบฎเบฑเบšเบ‚เปเป‰เบกเบนเบ™เบˆเบฐเบšเปเปˆเบชเบฒเบกเบฒเบ”. เป€เบฎเบฑเบ”เปเบ™เบงเบ™เบฑเป‰เบ™.

เบงเบดเบ—เบตเบเบฒเบ™เบ—เบตเบชเบญเบ‡เปƒเบŠเป‰ เบฅเบฐเบšเบปเบšเบเบฒเบ™เปเบˆเป‰เบ‡เป€เบ•เบทเบญเบ™เป€เบซเบ”เบเบฒเบ™ (เบ•เบปเบงเป€เบฅเบทเบญเบเบฅเบฐเบšเบปเบš) เบชเบฐเปœเบญเบ‡เปƒเบซเป‰เป‚เบ”เบ OS. เบšเบปเบ”โ€‹เบ„เบงเบฒเบกโ€‹เบ™เบตเป‰โ€‹เบ›เบถเบโ€‹เบชเบฒโ€‹เบซเบฒโ€‹เบฅเบทโ€‹เบ›เบฐโ€‹เป€เบžเบ”โ€‹เบ—เบปเปˆเบงโ€‹เป„เบ›โ€‹เบ‚เบญเบ‡โ€‹เบ•เบปเบงโ€‹เป€เบฅเบทเบญเบโ€‹เบฅเบฐโ€‹เบšเบปเบšโ€‹, เป‚เบ”เบโ€‹เบญเบตเบ‡โ€‹เปƒเบชเปˆโ€‹เบเบฒเบ™โ€‹เปเบˆเป‰เบ‡โ€‹เป€เบ•เบทเบญเบ™ (เป€เบซเบ”โ€‹เบเบฒเบ™โ€‹, เบเบฒเบ™โ€‹เปเบˆเป‰เบ‡โ€‹เบเบฒเบ™โ€‹) เบเปˆเบฝเบงโ€‹เบเบฑเบšโ€‹เบเบฒเบ™โ€‹เบเบฝเบกโ€‹เบžเป‰เบญเบกโ€‹เบชเปเบฒโ€‹เบฅเบฑเบšโ€‹เบเบฒเบ™โ€‹เบ”เปเบฒโ€‹เป€เบ™เบตเบ™โ€‹เบ‡เบฒเบ™ I/Oโ€‹, เปเบ—เบ™โ€‹เบ—เบตเปˆโ€‹เบˆเบฐโ€‹เป€เบ›เบฑเบ™โ€‹. เปเบˆเป‰เบ‡เบเบฒเบ™เบเปˆเบฝเบงเบเบฑเบšเบเบฒเบ™เบชเปเบฒเป€เบฅเบฑเบ”เบ‚เบญเบ‡เป€เบ‚เบปเบฒเป€เบˆเบปเป‰เบฒ. เบ•เบปเบงเบขเปˆเบฒเบ‡เบ—เบตเปˆเบ‡เปˆเบฒเบเบ”เบฒเบเบ‚เบญเบ‡เบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰เบ‚เบญเบ‡เบกเบฑเบ™เบชเบฒเบกเบฒเบ”เบ–เบทเบเบชเบฐเปเบ”เบ‡เป‚เบ”เบเปเบœเบ™เบงเบฒเบ”เบ•เบฑเบ™เบ•เปเปˆเป„เบ›เบ™เบตเป‰:

เป€เบ•เบปเบฒเบ›เบฐเบ•เบดเบเบญเบ™ C I/O เป€เบ›เบปเปˆเบฒเบกเบตเบ„เบธเบ™เบชเบปเบกเบšเบฑเบ”เป€เบ•เบฑเบกเบฎเบนเบšเปเบšเบš

เบ„เบงเบฒเบกเปเบ•เบเบ•เปˆเบฒเบ‡เบฅเบฐเบซเบงเปˆเบฒเบ‡เบงเบดเบ—เบตเบเบฒเบ™เป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰เปเบกเปˆเบ™เบกเบตเบ”เบฑเปˆเบ‡เบ™เบตเป‰:

  • เบเบฒเบ™เบ‚เบฑเบ”เบ‚เบงเบฒเบ‡เบเบฒเบ™เบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™ I/O เป‚เบˆเบฐ เบเบฐเปเบชเบœเบนเป‰เปƒเบŠเป‰ เบˆเบปเบ™เบเปˆเบงเบฒเบˆเบปเบ™เบเปˆเบงเบฒ OS เบ–เบทเบเบ•เป‰เบญเบ‡ defragments เบ‚เบฒเป€เบ‚เบปเป‰เบฒ เบŠเบธเบ” IP เบเบฑเบš byte stream (TCP, เบเบฒเบ™โ€‹เบฎเบฑเบšโ€‹เบ‚เปเป‰โ€‹เบกเบนเบ™โ€‹) เบซเบผเบทโ€‹เบˆเบฐโ€‹เบšเปเปˆโ€‹เบกเบตโ€‹เบžเบทเป‰เบ™โ€‹เบ—เบตเปˆโ€‹เบžเบฝเบ‡โ€‹เบžเปโ€‹เบ—เบตเปˆโ€‹เบกเบตโ€‹เบขเบนเปˆโ€‹เปƒเบ™โ€‹เบเบฒเบ™โ€‹เบšเบฑเบ™โ€‹เบ—เบถเบโ€‹เบเบฒเบ™โ€‹เบ‚เบฝเบ™โ€‹เบžเบฒเบโ€‹เปƒเบ™โ€‹เบชเปเบฒโ€‹เบฅเบฑเบšโ€‹เบเบฒเบ™โ€‹เบชเบปเปˆเบ‡โ€‹เบ•เปเปˆโ€‹เบกเบฒโ€‹เป‚เบ”เบโ€‹เบœเปˆเบฒเบ™โ€‹เบเบฒเบ™ NIC (เบชเบปเปˆเบ‡เบ‚เปเป‰เบกเบนเบ™).
  • เบ•เบปเบงเป€เบฅเบทเบญเบเบฅเบฐเบšเบปเบš เบฅเปˆเบงเบ‡โ€‹เป€เบงโ€‹เบฅเบฒ เปเบˆเป‰เบ‡เป‚เบ„เบ‡เบเบฒเบ™เบงเปˆเบฒ OS เปเบฅเป‰เบง เบŠเบธเบ” IP defragmented (TCP, เบเบฒเบ™เบฎเบฑเบšเบ‚เปเป‰เบกเบนเบ™) เบซเบผเบทเบžเบทเป‰เบ™เบ—เบตเปˆเบžเบฝเบ‡เบžเปเปƒเบ™ buffers เบ‚เบฝเบ™เบžเบฒเบเปƒเบ™ เปเบฅเป‰เบง เบชเบฒเบกเบฒเบ”เปƒเบŠเป‰เป„เบ”เป‰ (เบชเบปเปˆเบ‡เบ‚เปเป‰เบกเบนเบ™).

เป€เบžเบทเปˆเบญเบชเบฐเบซเบผเบธเบšเบกเบฑเบ™, เบเบฒเบ™เบˆเบญเบ‡เบเบฐเบ—เบนเป‰ OS เบชเปเบฒเบฅเบฑเบšเปเบ•เปˆเบฅเบฐ I / O เปเบกเปˆเบ™เป€เบชเบเบžเบฐเบฅเบฑเบ‡เบ‡เบฒเบ™เบ„เบญเบกเบžเบดเบงเป€เบ•เบตเป‰, เป€เบžเบฒเบฐเบงเปˆเบฒเปƒเบ™เบ„เบงเบฒเบกเป€เบ›เบฑเบ™เบˆเบดเบ‡, เบเบฐเบ—เบนเป‰เบšเปเปˆเป„เบ”เป‰เป€เบฎเบฑเบ”เบงเบฝเบเบ—เบตเปˆเป€เบ›เบฑเบ™เบ›เบฐเป‚เบซเบเบ” (เป€เบžเบฒเบฐเบชเบฐเบ™เบฑเป‰เบ™เบ„เปเบฒเบชเบฑเบš. "เบŠเบญเบšเปเบงเบ‚เบฑเบ”เบ‚เบงเบฒเบ‡"). เบ•เบปเบงเป€เบฅเบทเบญเบเบฅเบฐเบšเบปเบšเปเบเป‰เป„เบ‚เบšเบฑเบ™เบซเบฒเบ™เบตเป‰, เบญเบฐเบ™เบธเบเบฒเบ”เปƒเบซเป‰เป‚เบ„เบ‡เบเบฒเบ™เบœเบนเป‰เปƒเบŠเป‰เบชเบฒเบกเบฒเบ”เบ™เปเบฒเปƒเบŠเป‰เบŠเบฑเบšเบžเบฐเบเบฒเบเบญเบ™ CPU เป„เบ”เป‰เบซเบผเบฒเบเบ—เบฒเบ‡เบ”เป‰เบฒเบ™เป€เบชเบ”เบ–เบฐเบเบดเบ”.

เบฎเบนเบšเปเบšเบšเป€เบ„เบทเปˆเบญเบ‡เบ›เบฐเบ•เบดเบเบญเบ™ I/O

เป€เบ„เบทเปˆเบญเบ‡เบ›เบฐเบ•เบดเบเบญเบ™ I/O เป€เบฎเบฑเบ”เปœเป‰เบฒเบ—เบตเปˆเป€เบ›เบฑเบ™เบŠเบฑเป‰เบ™เบฅเบฐเบซเบงเปˆเบฒเบ‡เบ•เบปเบงเป€เบฅเบทเบญเบเบฅเบฐเบšเบปเบš เปเบฅเบฐเบฅเบฐเบซเบฑเบ”เบœเบนเป‰เปƒเบŠเป‰. เบซเบผเบฑเบเบเบฒเบ™เบ‚เบญเบ‡เบเบฒเบ™เบ”เปเบฒเป€เบ™เบตเบ™เบ‡เบฒเบ™เบ‚เบญเบ‡เบกเบฑเบ™เบ–เบทเบเบญเบฐเบ—เบดเบšเบฒเบเป‚เบ”เบเปเบœเบ™เบงเบฒเบ”เบ•เบฑเบ™เบ•เปเปˆเป„เบ›เบ™เบตเป‰:

เป€เบ•เบปเบฒเบ›เบฐเบ•เบดเบเบญเบ™ C I/O เป€เบ›เบปเปˆเบฒเบกเบตเบ„เบธเบ™เบชเบปเบกเบšเบฑเบ”เป€เบ•เบฑเบกเบฎเบนเบšเปเบšเบš

  • เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเบ‚เปเป€เบ•เบทเบญเบ™เบ—เปˆเบฒเบ™เบงเปˆเบฒเป€เบซเบ”เบเบฒเบ™เบซเบ™เบถเปˆเบ‡เปเบกเปˆเบ™เบเบฒเบ™เปเบˆเป‰เบ‡เป€เบ•เบทเบญเบ™เบงเปˆเบฒเป€เบ•เบปเป‰เบฒเบชเบฝเบšเบ—เบตเปˆเปเบ™เปˆเบ™เบญเบ™เบชเบฒเบกเบฒเบ”เบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™ I/O เบ—เบตเปˆเบšเปเปˆเบชเบฐเบเบฑเบ”เบเบฑเป‰เบ™.
  • เบ•เบปเบงเบˆเบฑเบ”เบเบฒเบ™เป€เบซเบ”เบเบฒเบ™เปเบกเปˆเบ™เบซเบ™เป‰เบฒเบ—เบตเปˆเป€เบญเบตเป‰เบ™เป‚เบ”เบเป€เบ„เบทเปˆเบญเบ‡เบ›เบฐเบ•เบดเบเบญเบ™ I/O เป€เบกเบทเปˆเบญเป„เบ”เป‰เบฎเบฑเบšเป€เบซเบ”เบเบฒเบ™, เป€เบŠเบดเปˆเบ‡เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™ I/O เบ—เบตเปˆเบšเปเปˆเบชเบฐเบเบฑเบ”เบเบฑเป‰เบ™.

เบกเบฑเบ™เป€เบ›เบฑเบ™เบชเบดเปˆเบ‡เบชเปเบฒเบ„เบฑเบ™เบ—เบตเปˆเบˆเบฐเบชเบฑเบ‡เป€เบเบ”เบงเปˆเบฒเป€เบ„เบทเปˆเบญเบ‡เบ›เบฐเบ•เบดเบเบญเบ™ I / O เปเบกเปˆเบ™เบ•เบฒเบกเบ„เปเบฒเบ™เบดเบเบฒเบกเบ”เบฝเบงเบเบฐเบ—เบนเป‰, เปเบ•เปˆเบšเปเปˆเบกเบตเบซเบเบฑเบ‡เบขเบธเบ”เปเบ™เบงเบ„เบงเบฒเบกเบ„เบดเบ”เบˆเบฒเบเบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰เปƒเบ™เบชเบฐเบžเบฒเบšเปเบงเบ”เบฅเป‰เบญเบกเบซเบผเบฒเบ threaded เปƒเบ™เบญเบฑเบ”เบ•เบฒเบชเปˆเบงเบ™เบ‚เบญเบ‡ 1 thread: เป€เบ•เบปเบฒเบ›เบฐเบ•เบดเบเบญเบ™ 1, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบเบฒเบ™ recycle cores CPU เบ—เบฑเบ‡เบซเบกเบปเบ”.

ะ ะตะฐะปะธะทะฐั†ะธั

เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเบงเบฒเบ‡เบเบฒเบ™เป‚เบ•เป‰เบ•เบญเบšเบชเบฒเบ—เบฒเบฅเบฐเบ™เบฐเปƒเบ™เป„เบŸเบฅเปŒ reactor.h, เปเบฅเบฐเบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ” - เปƒเบ™ reactor.c. reactor.h เบˆเบฐโ€‹เบ›เบฐโ€‹เบเบญเบšโ€‹เบ”เป‰เบงเบโ€‹เบเบฒเบ™โ€‹เบ›เบฐโ€‹เบเบฒเบ”โ€‹เบ”เบฑเปˆเบ‡โ€‹เบ•เปเปˆโ€‹เป„เบ›โ€‹เบ™เบตเป‰โ€‹:

เบชเบฐเปเบ”เบ‡เบเบฒเบ™เบ›เบฐเบเบฒเบ”เปƒเบ™ 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 เบ›เบฐเบเบญเบšเบ”เป‰เบงเบ เบ•เบปเบงเบญเบฐเบ—เบดเบšเบฒเบเป„เบŸเบฅเปŒ เป‚เบ•เป€เบฅเบทเบญเบ epol ะธ เบ•เบฒเบ•เบฐเบฅเบฒเบ‡ hash GHashTable, เป€เบŠเบดเปˆเบ‡เปเบœเบ™เบ—เบตเปˆเปเบ•เปˆเบฅเบฐเบŠเบฑเบญเบเป€เบเบฑเบ”เป„เบ›เบซเบฒ CallbackData (เป‚เบ„เบ‡เบชเป‰เบฒเบ‡เบ‚เบญเบ‡เบ•เบปเบงเบˆเบฑเบ”เบเบฒเบ™เป€เบซเบ”เบเบฒเบ™เปเบฅเบฐเบเบฒเบ™เป‚เบ•เป‰เบ–เบฝเบ‡เบ‚เบญเบ‡เบœเบนเป‰เปƒเบŠเป‰เบชเปเบฒเบฅเบฑเบšเบกเบฑเบ™).

เบชเบฐเปเบ”เบ‡ Reactor เปเบฅเบฐ CallbackData

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

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

เบเบฐเบฅเบธเบ™เบฒเบชเบฑเบ‡เป€เบเบ”เบงเปˆเบฒเบžเบงเบเป€เบฎเบปเบฒเป„เบ”เป‰เป€เบ›เบตเบ”เปƒเบŠเป‰เบ„เบงเบฒเบกเบชเบฒเบกเบฒเบ”เปƒเบ™เบเบฒเบ™เบˆเบฑเบ”เบเบฒเบ™ เบ›เบฐเป€เบžเบ”เบšเปเปˆเบ„เบปเบšเบ–เป‰เบงเบ™ เบญเบตเบ‡เบ•เบฒเบกเบ”เบฑเบ”เบŠเบฐเบ™เบต. IN reactor.h เบžเบงเบเป€เบฎเบปเบฒเบ›เบฐเบเบฒเบ”เป‚เบ„เบ‡เบชเป‰เบฒเบ‡ reactor, เปเบฅเบฐเปƒเบ™ reactor.c เบžเบงเบเป€เบฎเบปเบฒเบเปเบฒเบ™เบปเบ”เบกเบฑเบ™, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบเบฒเบ™เบ›เป‰เบญเบ‡เบเบฑเบ™เบœเบนเป‰เปƒเบŠเป‰เบˆเบฒเบเบเบฒเบ™เบ›เปˆเบฝเบ™เปเบ›เบ‡เบ—เบปเปˆเบ‡เบ™เบฒเบ‚เบญเบ‡เบ•เบปเบ™เบขเปˆเบฒเบ‡เบŠเบฑเบ”เป€เบˆเบ™. เบ™เบตเป‰เปเบกเปˆเบ™เบซเบ™เบถเปˆเบ‡เปƒเบ™เบฎเบนเบšเปเบšเบš เป€เบŠเบทเปˆเบญเบ‡เบ‚เปเป‰เบกเบนเบ™, เป€เบŠเบดเปˆเบ‡ succinctly fits เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™ C semantics.

เบŸเบฑเบ‡เบŠเบฑเบ™ reactor_register, reactor_deregister ะธ reactor_reregister เบ›เบฑเบšเบ›เบธเบ‡เบšเบฑเบ™เบŠเบตเบฅเบฒเบเบŠเบทเปˆเบ‚เบญเบ‡เป€เบ•เบปเป‰เบฒเบฎเบฑเบšเบ„เบงเบฒเบกเบชเบปเบ™เปƒเบˆเปเบฅเบฐเบ•เบปเบงเบˆเบฑเบ”เบเบฒเบ™เป€เบซเบ”เบเบฒเบ™เบ—เบตเปˆเบชเบญเบ”เบ„เป‰เบญเบ‡เบเบฑเบ™เบขเบนเปˆเปƒเบ™เบ•เบปเบงเป€เบฅเบทเบญเบเบฅเบฐเบšเบปเบšเปเบฅเบฐเบ•เบฒเบ•เบฐเบฅเบฒเบ‡ hash.

เบชเบฐเปเบ”เบ‡เบซเบ™เป‰เบฒเบ—เบตเปˆเบฅเบปเบ‡เบ—เบฐเบšเบฝเบ™

#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 เป€เบ›เบปเปˆเบฒเบกเบตเบ„เบธเบ™เบชเบปเบกเบšเบฑเบ”เป€เบ•เบฑเบกเบฎเบนเบšเปเบšเบš

เป€เบŠเบตเบšเป€เบงเบตเบเบฐเบ—เบนเป‰เบ”เบฝเบง

เป€เบžเบทเปˆเบญเบ—เบปเบ”เบชเบญเบšเป€เบ„เบทเปˆเบญเบ‡เบ›เบฐเบ•เบดเบเบญเบ™ I/O เบžเบฒเบเปƒเบ•เป‰เบเบฒเบ™เป‚เบซเบผเบ”เบชเบนเบ‡, เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเบ‚เบฝเบ™เป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบเป€เบงเบฑเบšเป„เบŠเบ•เปŒ HTTP เปเบšเบšเบ‡เปˆเบฒเบเบ”เบฒเบเบ—เบตเปˆเบ•เบญเบšเบชเบฐเบซเบ™เบญเบ‡เบ„เปเบฒเบฎเป‰เบญเบ‡เบ‚เปเปƒเบ”เป†เบ—เบตเปˆเบกเบตเบฎเบนเบšเบžเบฒเบš.

เบเบฒเบ™เบญเป‰เบฒเบ‡เบญเบตเบ‡เป„เบงเบ•เปเปˆเบเบฑเบšเป‚เบ›เบฃเป‚เบ•เบ„เป HTTP

HTTP - เบ™เบตเป‰เปเบกเปˆเบ™เบžเบดเบ—เบตเบเบฒเบ™ เบฅเบฐเบ”เบฑเบšเบ„เปเบฒเบฎเป‰เบญเบ‡เบชเบฐเบซเบกเบฑเบ, เบ•เบปเป‰เบ™เบ•เปเปเบกเปˆเบ™เปƒเบŠเป‰เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เป‚เบ•เป‰เบ•เบญเบšเบเบฑเบšเป€เบŠเบตเบšเป€เบงเบต-เบšเบฃเบฒเบงเป€เบŠเบต.

HTTP เบชเบฒเบกเบฒเบ”เบ–เบทเบเบ™เปเบฒเปƒเบŠเป‰เป„เบ”เป‰เบ‡เปˆเบฒเบเบเบงเปˆเบฒ เบเบฒเบ™เบ‚เบปเบ™เบชเบปเปˆเบ‡ เบžเบดเบ—เบตเบเบฒเบ™ TCP, เบเบฒเบ™เบชเบปเปˆเบ‡เปเบฅเบฐเบฎเบฑเบšเบ‚เปเป‰เบ„เบงเบฒเบกเปƒเบ™เบฎเบนเบšเปเบšเบšเบ—เบตเปˆเบฅเบฐเบšเบธเป„เบงเป‰ เบชเบฐเป€เบžเบฒเบฐ.

เบฎเบนเบšเปเบšเบšเบเบฒเบ™เบฎเป‰เบญเบ‡เบ‚เป

<ะšะžะœะะะ”ะ> <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 protocol เปƒเบ™เบฎเบนเบšเปเบšเบš HTTP/X.Y. เบชเบฐเบšเบฑเบšเบ—เบตเปˆเปƒเบŠเป‰เบ—เบปเปˆเบงเป„เบ›เบ—เบตเปˆเบชเบธเบ”เปƒเบ™เบกเบทเป‰เบ™เบตเป‰เปเบกเปˆเบ™ HTTP/1.1.
  • <ะ—ะะ“ะžะ›ะžะ’ะžะš N> เปเบกเปˆเบ™เบ„เบนเปˆเบ„เบต-เบ„เปˆเบฒเปƒเบ™เบฎเบนเบšเปเบšเบš <ะšะ›ะฎะง>: <ะ—ะะะงะ•ะะ˜ะ•>, เบ–เบทเบเบชเบปเปˆเบ‡เป„เบ›เบซเบฒเป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบงเบดเป€เบ„เบฒเบฐเบ•เบทเปˆเบกเบญเบตเบ.
  • <ะ”ะะะะซะ•> โ€” เบ‚เปเป‰โ€‹เบกเบนเบ™โ€‹เบ—เบตเปˆโ€‹เบ•เป‰เบญเบ‡โ€‹เบเบฒเบ™โ€‹เป‚เบ”เบโ€‹เป€เบ„เบทเปˆเบญเบ‡โ€‹เปเบกเปˆโ€‹เบ‚เปˆเบฒเบโ€‹เปƒเบ™โ€‹เบเบฒเบ™โ€‹เบ”เปเบฒโ€‹เป€เบ™เบตเบ™โ€‹เบเบฒเบ™โ€‹. เป€เบฅเบทเป‰เบญเบเป†เบกเบฑเบ™เบ‡เปˆเบฒเบเบ”เบฒเบ JSON เบซเบผเบทเบฎเบนเบšเปเบšเบšเบญเบทเปˆเบ™เป†.

เบฎเบนเบšโ€‹เปเบšเบšโ€‹เบเบฒเบ™โ€‹เบ•เบญเบšโ€‹เบชเบฐโ€‹เบซเบ™เบญเบ‡โ€‹

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

  • <ะšะžะ” ะกะขะะขะฃะกะ> เปเบกเปˆเบ™เบ•เบปเบงเป€เบฅเบเบ—เบตเปˆเบชเบฐเปเบ”เบ‡เบœเบปเบ™เบ‚เบญเบ‡เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบ‡เบฒเบ™. เป€เบŠเบตเบšเป€เบงเบตเบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเบชเบปเปˆเบ‡เบ„เบทเบ™เบชเบฐเบ–เบฒเบ™เบฐ 200 เบชเบฐเป€เปเบต (เบเบฒเบ™เบ”เบณเป€เบ™เบตเบ™เบเบฒเบ™เบ—เบตเปˆเบชเบณเป€เบฅเบฑเบ”).
  • <ะžะŸะ˜ะกะะะ˜ะ• ะกะขะะขะฃะกะ> โ€” เบ•เบปเบงโ€‹เปเบ—เบ™โ€‹เบชเบฒเบโ€‹เบ‚เบญเบ‡โ€‹เบฅเบฐโ€‹เบซเบฑเบ”โ€‹เบชเบฐโ€‹เบ–เบฒโ€‹เบ™เบฐโ€‹เบžเบฒเบšโ€‹. เบชเปเบฒเบฅเบฑเบšเบฅเบฐเบซเบฑเบ”เบชเบฐเบ–เบฒเบ™เบฐ 200 เบ™เบตเป‰เปเบกเปˆเบ™ OK.
  • <ะ—ะะ“ะžะ›ะžะ’ะžะš N> โ€” เบชเปˆเบงเบ™เบซเบปเบงเบ‚เบญเบ‡เบฎเบนเบšเปเบšเบšเบ”เบฝเบงเบเบฑเบ™เบเบฑเบšเบขเบนเปˆเปƒเบ™เบ„เปเบฒเบฎเป‰เบญเบ‡เบ‚เป. เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเบชเบปเปˆเบ‡เบ„เบทเบ™เบซเบปเบงเบ‚เปเป‰ Content-Length (เบ‚เบฐเบซเบ™เบฒเบ”เป„เบŸเบฅเปŒ) เปเบฅเบฐ Content-Type: text/html (เบ›เบฐเป€เบžเบ”เบ‚เปเป‰เบกเบนเบ™เบ„เบทเบ™).
  • <ะ”ะะะะซะ•> โ€” เบ‚เปเป‰โ€‹เบกเบนเบ™โ€‹เบ—เบตเปˆโ€‹เบฎเป‰เบญเบ‡โ€‹เบ‚เปโ€‹เป‚เบ”เบโ€‹เบœเบนเป‰โ€‹เปƒเบŠเป‰โ€‹. เปƒเบ™เบเปเบฅเบฐเบ™เบตเบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒ, เบ™เบตเป‰เปเบกเปˆเบ™เป€เบชเบฑเป‰เบ™เบ—เบฒเบ‡เป„เบ›เบชเบนเปˆเบฎเบนเบšเบžเบฒเบšเปƒเบ™ HTML.

เป€เบญเบเบฐเบชเบฒเบ™ http_server.c (เป€เบŠเบตเบšเป€เบงเบต threaded เบ”เบฝเบง) เบ›เบฐเบเบญเบšเบกเบตเป„เบŸเบฅเปŒ common.h, เป€เบŠเบดเปˆเบ‡เบ›เบฐเบเบญเบšเบ”เป‰เบงเบ prototypes เบซเบ™เป‰เบฒเบ—เบตเปˆเบ”เบฑเปˆเบ‡เบ•เปเปˆเป„เบ›เบ™เบตเป‰:

เบชเบฐเปเบ”เบ‡เบ•เบปเบงเปเบšเบšเบŸเบฑเบ‡เบŠเบฑเบ™เปƒเบ™ 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(). macro เบ›เบฝเบšเบ—เบฝเบšเบ„เปˆเบฒเบ‚เบญเบ‡เบเบฒเบ™เบชเบฐเปเบ”เบ‡เบœเบปเบ™เบเบฑเบšเบ„เบงเบฒเบกเบœเบดเบ”เบžเบฒเบ”, เปเบฅเบฐเบ–เป‰เบฒเป€เบ‡เบทเปˆเบญเบ™เป„เบ‚เป€เบ›เบฑเบ™เบˆเบดเบ‡, เป‚เบ—เบซเบฒเบŸเบฑเบ‡เบŠเบฑเบ™. fail():

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

เบเบฒเบ™เบ—เปเบฒเบ‡เบฒเบ™เบ‚เบญเบ‡ fail() เบžเบดเบกโ€‹เบเบฒเบ™โ€‹เป‚เบ•เป‰โ€‹เบ–เบฝเบ‡โ€‹เบ—เบตเปˆโ€‹เบœเปˆเบฒเบ™โ€‹เป„เบ›โ€‹เบ—เบตเปˆ terminal (เป€เบŠเบฑเปˆเบ™โ€‹:โ€‹ 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, เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เบŸเบฑเบ‡เบŠเบฑเบ™เบ™เบตเป‰เบˆเบฐ configure socket เบเบฑเบšเบ—เบฒเบ‡เป€เบฅเบทเบญเบ SO_REUSEPORT เบœเปˆเบฒเบ™ setsockopt()เป€เบžเบทเปˆเบญเปƒเบŠเป‰เบžเบญเบ”เบ”เบฝเบงเบเบฑเบ™เปƒเบ™เบชเบฐเบžเบฒเบšเปเบงเบ”เบฅเป‰เบญเบกเบซเบผเบฒเบเบเบฐเบ—เบนเป‰ (เป€เบšเบดเปˆเบ‡เบžเบฒเบ "เป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบเบซเบผเบฒเบเบเบฐเบ—เบนเป‰").

เบ•เบปเบงเบˆเบฑเบ”เบเบฒเบ™เป€เบซเบ”เบเบฒเบ™ on_accept() เป€เบญเบตเป‰เบ™เบงเปˆเบฒเบซเบผเบฑเบ‡เบˆเบฒเบ OS เบชเป‰เบฒเบ‡เป€เบซเบ”เบเบฒเบ™ 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() เป€เบญเบตเป‰เบ™เบงเปˆเบฒเบซเบผเบฑเบ‡เบˆเบฒเบ OS เบชเป‰เบฒเบ‡เป€เบซเบ”เบเบฒเบ™ EPOLLIN, เปƒเบ™เบเปเบฅเบฐเบ™เบตเบ™เบตเป‰เบซเบกเบฒเบเบ„เบงเบฒเบกเบงเปˆเบฒเบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเบ—เบตเปˆเบฅเบปเบ‡เบ—เบฐเบšเบฝเบ™ on_accept(), เบžเป‰เบญเบกเบ—เบตเปˆเบˆเบฐเบฎเบฑเบšเบ‚เปเป‰เบกเบนเบ™.

on_recv() เบญเปˆเบฒเบ™เบ‚เปเป‰เบกเบนเบ™เบˆเบฒเบเบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเบˆเบปเบ™เบเปˆเบงเบฒเบเบฒเบ™เบฎเป‰เบญเบ‡เบ‚เป HTTP เป„เบ”เป‰เบฎเบฑเบšเบขเปˆเบฒเบ‡เบชเบปเบกเบšเบนเบ™, เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เบกเบฑเบ™เบฅเบปเบ‡เบ—เบฐเบšเบฝเบ™เบ•เบปเบงเบˆเบฑเบ”เบเบฒเบ™ on_send() เป€เบžเบทเปˆเบญเบชเบปเปˆเบ‡เบ„เปเบฒเบ•เบญเบš HTTP. เบ–เป‰เบฒเบฅเบนเบเบ„เป‰เบฒเบ—เปเบฒเบฅเบฒเบเบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆ, เป€เบ•เบปเป‰เบฒเบฎเบฑเบšเบ–เบทเบเบเบปเบเป€เบฅเบตเบเบเบฒเบ™เบฅเบปเบ‡เบ—เบฐเบšเบฝเบ™เปเบฅเบฐเบ›เบดเบ”เป‚เบ”เบเปƒเบŠเป‰ 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() เป€เบญเบตเป‰เบ™เบงเปˆเบฒเบซเบผเบฑเบ‡เบˆเบฒเบ OS เบชเป‰เบฒเบ‡เป€เบซเบ”เบเบฒเบ™ EPOLLOUT, เบซเบกเบฒเบเบ„เบงเบฒเบกเบงเปˆเบฒเบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเป„เบ”เป‰เบฅเบปเบ‡เบ—เบฐเบšเบฝเบ™ on_recv(), เบžเป‰เบญเบกเบ—เบตเปˆเบˆเบฐเบชเบปเปˆเบ‡เบ‚เปเป‰เบกเบนเบ™. เบŸเบฑเบ‡เบŠเบฑเบ™เบ™เบตเป‰เบชเบปเปˆเบ‡เบ„เปเบฒเบ•เบญเบš HTTP เบ—เบตเปˆเบกเบต 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() เบžเบงเบเป€เบฎเบปเบฒเบชเป‰เบฒเบ‡เป€เบ•เบปเบฒเบ›เบฐเบ•เบดเบเบญเบ™ I/O เป‚เบ”เบเปƒเบŠเป‰ 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 เปƒเบ™ browser เปเบฅเบฐเป€เบšเบดเปˆเบ‡เบชเบดเปˆเบ‡เบ—เบตเปˆเบžเบงเบเป€เบฎเบปเบฒเบ„เบฒเบ”เบซเบงเบฑเบ‡:

เป€เบ•เบปเบฒเบ›เบฐเบ•เบดเบเบญเบ™ 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

เปƒเบซเป‰เบงเบฑเบ”เปเบ—เบเบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบšเบ‚เบญเบ‡เป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบเบ—เบตเปˆเบกเบตเบเบฐเบ—เบนเป‰เบ”เบฝเบง. เปƒเบซเป‰เป€เบ›เบตเบ”เบชเบญเบ‡ terminals: เปƒเบ™เบซเบ™เบถเปˆเบ‡เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™ ./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 เบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆ. เบšเปเปˆเปเบกเปˆเบ™เบœเบปเบ™เป„เบ”เป‰เบฎเบฑเบšเบ—เบตเปˆเบšเปเปˆเบ”เบต, เปเบ•เปˆเบชเบฒเบกเบฒเบ”เบ›เบฑเบšเบ›เบธเบ‡เป„เบ”เป‰เบšเป?

เป€เบŠเบตเบšเป€เบงเบต Multithreaded

เบ”เบฑเปˆเบ‡เบ—เบตเปˆเป„เบ”เป‰เบเปˆเบฒเบงเบกเบฒเบ‚เป‰เบฒเบ‡เป€เบ—เบดเบ‡, เป€เบ„เบทเปˆเบญเบ‡เบ›เบฐเบ•เบดเบเบญเบ™ I/O เบชเบฒเบกเบฒเบ”เบ–เบทเบเบชเป‰เบฒเบ‡เบ‚เบทเป‰เบ™เปƒเบ™เบเบฐเบ—เบนเป‰เปเบเบเบ•เปˆเบฒเบ‡เบซเบฒเบ, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰เปเบเบ™ CPU เบ—เบฑเบ‡เบซเบกเบปเบ”. เปƒเบซเป‰เบžเบงเบเป€เบฎเบปเบฒเป€เบญเบปเบฒเบงเบดเบ—เบตเบ™เบตเป‰เป„เบ›เบ›เบฐเบ•เบดเบšเบฑเบ”:

เบชเบฐเปเบ”เบ‡ 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, เบเบฒเบ™เป€เบžเบตเปˆเบกเบ‚เบถเป‰เบ™เบ‚เบญเบ‡เบˆเปเบฒเบ™เบงเบ™ hits เปเบ„เบ”, เป€เบžเบตเปˆเบกโ€‹เบ‚เบถเป‰เบ™ 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 stack เบšเป? เบฎเบนเป‰เบชเบถเบเบšเปเปˆเป€เบชเบเบ„เปˆเบฒเบ—เบตเปˆเบˆเบฐเบ‚เบฝเบ™เบชเบปเบกเบกเบธเบ”เบ•เบดเบ–เบฒเบ™เบ‚เบญเบ‡เบ—เปˆเบฒเบ™เบเปˆเบฝเบงเบเบฑเบšเบžเบถเบ”เบ•เบดเบเปเบฒเบ™เบตเป‰เบ‚เบญเบ‡เบเบฒเบŸเปเบฅเบฐเบเบฒเบ™เป€เบžเบตเปˆเบกเบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบšเบชเปเบฒเบฅเบฑเบšเบ—เบฒเบ‡เป€เบฅเบทเบญเบเบซเบผเบฒเบเบเบฐเบ—เบนเป‰เปเบฅเบฐเบเบฐเบ—เบนเป‰เบ”เบฝเบงเปƒเบ™เบ„เปเบฒเป€เบซเบฑเบ™.

เบงเบดโ€‹เบ—เบตโ€‹เบเบฒเบ™ เบชเบฑเบ‡เป€เบเบ”เป€เบซเบฑเบ™ เปƒเบ™เบ„เปเบฒเป€เบซเบฑเบ™, เบเบฒเบ™เบ—เบปเบ”เบชเบญเบšเบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบ™เบตเป‰เบšเปเปˆเป„เบ”เป‰เบชเบฐเปเบ”เบ‡เปƒเบซเป‰เป€เบซเบฑเบ™เบžเบถเบ”เบ•เบดเบเปเบฒเบ‚เบญเบ‡ I / O reactor เบžเบฒเบเปƒเบ•เป‰เบเบฒเบ™เป‚เบซเบผเบ”เบ—เบตเปˆเปเบ—เป‰เบˆเบดเบ‡, เป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบงเปˆเบฒเป€เบเบทเบญเบšเบชเบฐเป€เบซเบกเบตเป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบเบžเบปเบงเบžเบฑเบ™เบเบฑเบšเบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™, เบšเบฑเบ™เบ—เบถเบเบœเบปเบ™เป„เบ”เป‰เบฎเบฑเบš, เปƒเบŠเป‰ cryptography เบเบฑเบš. TLS เปเบฅเบฐเบญเบทเปˆเบ™เป†, เป€เบ›เบฑเบ™เบœเบปเบ™เบกเบฒเบˆเบฒเบเบเบฒเบ™เป‚เบซเบผเบ”เป„เบ”เป‰เบเบฒเบเป€เบ›เบฑเบ™เบ—เบตเปˆเบšเปเปˆเป€เบ›เบฑเบ™เป€เบญเบเบฐเบžเบฒเบš (dynamic). เบเบฒเบ™เบ—เบปเบ”เบชเบญเบšเบฎเปˆเบงเบกเบเบฑเบšเบญเบปเบ‡เบ›เบฐเบเบญเบšเบ‚เบญเบ‡เบžเบฒเบเบชเปˆเบงเบ™เบ—เบตเบชเบฒเบกเบˆเบฐเบ–เบทเบเบ”เปเบฒเป€เบ™เบตเบ™เบขเบนเปˆเปƒเบ™เบšเบปเบ”เบ„เบงเบฒเบกเบเปˆเบฝเบงเบเบฑเบš I/O proactor.

เบ‚เปเป‰เป€เบชเบเบ‚เบญเบ‡เป€เบ„เบทเปˆเบญเบ‡เบ›เบฐเบ•เบดเบเบญเบ™ I/O

เบ—เปˆเบฒเบ™เบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡เป€เบ‚เบปเป‰เบฒเปƒเบˆเบงเปˆเบฒ I/O reactor เบšเปเปˆเปเบกเปˆเบ™เบšเปเปˆเบกเบตเบ‚เปเป‰เบšเบปเบเบœเปˆเบญเบ‡เบ‚เบญเบ‡เบกเบฑเบ™, เบ„เบท:

  • เบเบฒเบ™เปƒเบŠเป‰เป€เบ•เบปเบฒเบ›เบฐเบ•เบดเบเบญเบ™ I/O เปƒเบ™เบชเบฐเบžเบฒเบšเปเบงเบ”เบฅเป‰เบญเบกเบซเบผเบฒเบเบเบฐเบ—เบนเป‰เปเบกเปˆเบ™เบกเบตเบ„เบงเบฒเบกเบซเบเบธเป‰เบ‡เบเบฒเบเบซเบผเบฒเบ, เป€เบžเบฒเบฐเบงเปˆเบฒ เบ—เปˆเบฒเบ™เบˆเบฐเบ•เป‰เบญเบ‡เบˆเบฑเบ”เบเบฒเบ™เบเบฒเบ™เป„เบซเบผเป€เบ‚เบปเป‰เบฒเบ”เป‰เบงเบเบ•เบปเบ™เป€เบญเบ‡.
  • เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบชเบฐเปเบ”เบ‡เปƒเบซเป‰เป€เบซเบฑเบ™เบงเปˆเบฒเปƒเบ™เบเปเบฅเบฐเบ™เบตเบซเบผเบฒเบเบ—เบตเปˆเบชเบธเบ”, เบเบฒเบ™เป‚เบซเบผเบ”เปเบกเปˆเบ™เบšเปเปˆเป€เบ›เบฑเบ™เป€เบญเบเบฐเบžเบฒเบš, เป€เบŠเบดเปˆเบ‡เบชเบฒเบกเบฒเบ”เบ™เปเบฒเป„เบ›เบชเบนเปˆเบเบฒเบ™เบ•เบฑเบ”เป„เบกเป‰เป€เบชเบฑเป‰เบ™เบซเบ™เบถเปˆเบ‡เปƒเบ™เบ‚เบฐเบ™เบฐเบ—เบตเปˆเบ„เบปเบ™เบญเบทเปˆเบ™เบเปเบฒเบฅเบฑเบ‡เบซเบเบธเป‰เบ‡เบเบฑเบšเบงเบฝเบ.
  • เบ–เป‰เบฒเบ•เบปเบงเบˆเบฑเบ”เบเบฒเบ™เป€เบซเบ”เบเบฒเบ™เบซเบ™เบถเปˆเบ‡เบšเบฅเบฑเบญเบเบเบฐเบ—เบนเป‰, เบ•เบปเบงเป€เบฅเบทเบญเบเบฅเบฐเบšเบปเบšเบ•เบปเบงเบกเบฑเบ™เป€เบญเบ‡เบเบฑเบ‡เบˆเบฐเบšเบฅเบฑเบญเบ, เป€เบŠเบดเปˆเบ‡เบชเบฒเบกเบฒเบ”เบ™เปเบฒเป„เบ›เบชเบนเปˆเบเบฒเบ™เบเบฒเบเบ—เบตเปˆเบˆเบฐเบŠเบญเบเบซเบฒเบ‚เปเป‰เบšเบปเบเบžเปˆเบญเบ‡.

เปเบเป‰เป„เบ‚เบšเบฑเบ™เบซเบฒเป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰ I/O proactor, เป€เบŠเบดเปˆเบ‡เบกเบฑเบเบˆเบฐเบกเบตเบ•เบปเบงเบเปเบฒเบ™เบปเบ”เป€เบงเบฅเบฒเบ—เบตเปˆเปเบˆเบเบขเบฒเบเบเบฒเบ™เป‚เบซเบผเบ”เป€เบ—เบปเปˆเบฒเบ—เบฝเบกเบเบฑเบ™เบเบฑเบšเบชเบฐเบ™เบธเบเป€เบเบตเบ‚เบญเบ‡เบเบฐเบ—เบนเป‰, เปเบฅเบฐเบเบฑเบ‡เบกเบต API เบ—เบตเปˆเบชเบฐเบ”เบงเบเบเบงเปˆเบฒ. เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเป€เบงเบปเป‰เบฒเบเปˆเบฝเบงเบเบฑเบšเบกเบฑเบ™เบ•เปเปˆเบกเบฒ, เปƒเบ™เบšเบปเบ”เบ„เบงเบฒเบกเบญเบทเปˆเบ™เบ‚เบญเบ‡เบ‚เป‰เบญเบ.

เบชเบฐเบซเบฅเบธเบš

เบ™เบตเป‰เปเบกเปˆเบ™เบšเปˆเบญเบ™เบ—เบตเปˆเบเบฒเบ™เป€เบ”เบตเบ™เบ—เบฒเบ‡เบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒเบˆเบฒเบเบ—เบดเบ”เบชเบฐเบ”เบตเป‚เบ”เบเบเบปเบ‡เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบ—เปเปˆ profiler เป„เบ”เป‰เบชเบดเป‰เบ™เบชเบธเบ”เบฅเบปเบ‡.

เบ—เปˆเบฒเบ™เบšเปเปˆเบ„เบงเบ™เบขเบนเปˆเบเบฑเบšเป€เบฅเบทเปˆเบญเบ‡เบ™เบตเป‰, เป€เบžเบฒเบฐเบงเปˆเบฒเบกเบตเบงเบดเบ—เบตเบเบฒเบ™เบญเบทเปˆเบ™เป†เบ—เบตเปˆเบซเบ™เป‰เบฒเบชเบปเบ™เปƒเบˆเป€เบ—เบปเปˆเบฒเบ—เบฝเบกเบเบฑเบ™เปƒเบ™เบเบฒเบ™เบ‚เบฝเบ™เป‚เบ›เบผเปเบเบผเบกเป€เบ„เบทเบญเบ‚เปˆเบฒเบเบ—เบตเปˆเบกเบตเบฅเบฐเบ”เบฑเบšเบ„เบงเบฒเบกเบชเบฐเบ”เบงเบเบชเบฐเบšเบฒเบเปเบฅเบฐเบ„เบงเบฒเบกเป„เบงเบ—เบตเปˆเปเบ•เบเบ•เปˆเบฒเบ‡เบเบฑเบ™. เบซเบ™เป‰เบฒเบชเบปเบ™เปƒเบˆ, เปƒเบ™เบ„เบงเบฒเบกเบ„เบดเบ”เป€เบซเบฑเบ™เบ‚เบญเบ‡เบ‚เป‰เบญเบ, เบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเปเบกเปˆเบ™เปƒเบซเป‰เบ‚เป‰เบฒเบ‡เบฅเบธเปˆเบกเบ™เบตเป‰.

ะฝะพะฝะพะฒั‹ั…ะฒัั‚ั€ะตั‡!

เป‚เบ„เบ‡เบเบฒเบ™เบ—เบตเปˆเบซเบ™เป‰เบฒเบชเบปเบ™เปƒเบˆ

เบ‚เป‰เบญเบเบ„เบงเบ™เบญเปˆเบฒเบ™เบซเบเบฑเบ‡เบญเบตเบ?

เปเบซเบผเปˆเบ‡เบ‚เปเป‰เบกเบนเบ™: www.habr.com

เป€เบžเบตเปˆเบกเบ„เบงเบฒเบกเบ„เบดเบ”เป€เบซเบฑเบ™