āĻā§āĻŽāĻŋāĻāĻž
node.js āĻĒāĻžāĻšāĻžāĻĄāĻŧ āĻā§āĻ°āĻžāĻ¨ā§āĻ¸āĻŽāĻŋāĻļāĻ¨ āĻā§āĻ°ā§āĻŽāĻŋāĻ¯āĻŧāĻžāĻŽ memcached - ...
āĻāĻ āĻ¨āĻŋāĻŦāĻ¨ā§āĻ§ā§, āĻāĻŽāĻ°āĻž āĻāĻāĻāĻŋ I/O āĻā§āĻ˛ā§āĻ˛āĻŋāĻ° āĻāĻ¨āĻ¸ āĻāĻŦāĻ āĻāĻāĻāĻā§āĻ˛āĻŋ āĻĻā§āĻāĻŦ āĻāĻŦāĻ āĻāĻāĻŋ āĻā§āĻāĻžāĻŦā§ āĻāĻžāĻ āĻāĻ°ā§, 200 āĻ˛āĻžāĻāĻ¨ā§āĻ° āĻāĻŽ āĻā§āĻĄā§ āĻāĻāĻāĻŋ āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨ āĻ˛āĻŋāĻāĻŦ āĻāĻŦāĻ 40 āĻŽāĻŋāĻ˛āĻŋāĻ¯āĻŧāĻ¨ āĻ āĻ¨ā§āĻ°ā§āĻ§/āĻŽāĻŋāĻ¨āĻŋāĻā§āĻ° āĻŦā§āĻļāĻŋ āĻāĻāĻāĻŋ āĻ¸āĻžāĻ§āĻžāĻ°āĻŖ HTTP āĻ¸āĻžāĻ°ā§āĻāĻžāĻ° āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻ¤ā§āĻ°āĻŋ āĻāĻ°āĻŦā§ˇ
āĻā§āĻŽāĻŋāĻāĻž
- āĻ¨āĻŋāĻŦāĻ¨ā§āĻ§āĻāĻŋ I/O āĻā§āĻ˛ā§āĻ˛āĻŋāĻ° āĻāĻžāĻ°ā§āĻ¯āĻāĻžāĻ°āĻŋāĻ¤āĻž āĻŦā§āĻāĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻāĻŦāĻ āĻ¤āĻžāĻ āĻāĻāĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°āĻžāĻ° āĻ¸āĻŽāĻ¯āĻŧ āĻā§āĻāĻāĻŋāĻā§āĻ˛āĻŋ āĻŦā§āĻāĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻ˛ā§āĻāĻž āĻšāĻ¯āĻŧā§āĻāĻŋāĻ˛āĨ¤
- āĻ¨āĻŋāĻŦāĻ¨ā§āĻ§āĻāĻŋ āĻŦā§āĻāĻ¤ā§ āĻĒā§āĻ°āĻžāĻĨāĻŽāĻŋāĻ āĻā§āĻāĻžāĻ¨ āĻĒā§āĻ°āĻ¯āĻŧā§āĻāĻ¨āĨ¤
āĻ¸āĻŋ āĻāĻžāĻˇāĻž āĻāĻŦāĻ āĻ¨ā§āĻāĻāĻ¯āĻŧāĻžāĻ°ā§āĻ āĻ ā§āĻ¯āĻžāĻĒā§āĻ˛āĻŋāĻā§āĻļāĻ¨ āĻŦāĻŋāĻāĻžāĻļā§ āĻāĻŋāĻā§ āĻ āĻāĻŋāĻā§āĻāĻ¤āĻžāĨ¤ - āĻ¸āĻŽāĻ¸ā§āĻ¤ āĻā§āĻĄ āĻāĻ ā§āĻ°āĻāĻžāĻŦā§ āĻ¸āĻŋ āĻāĻžāĻˇāĻžāĻ¯āĻŧ āĻ˛ā§āĻāĻž āĻšāĻ¯āĻŧ (āĻ¸āĻ¤āĻ°ā§āĻāĻ¤āĻž: āĻĻā§āĻ°ā§āĻ āĻĒāĻŋāĻĄāĻŋāĻāĻĢ)
C11 āĻ¸ā§āĻā§āĻ¯āĻžāĻ¨ā§āĻĄāĻžāĻ°ā§āĻĄā§ āĻ˛āĻŋāĻ¨āĻžāĻā§āĻ¸ā§āĻ° āĻāĻ¨ā§āĻ¯ āĻāĻŦāĻ āĻāĻĒāĻ˛āĻŦā§āĻ§GitHub .
āĻā§āĻ¨ āĻāĻ āĻĒā§āĻ°āĻ¯āĻŧā§āĻāĻ¨ā§āĻ¯āĻŧ?
āĻāĻ¨ā§āĻāĻžāĻ°āĻ¨ā§āĻā§āĻ° āĻā§āĻ°āĻŽāĻŦāĻ°ā§āĻ§āĻŽāĻžāĻ¨ āĻāĻ¨āĻĒā§āĻ°āĻŋāĻ¯āĻŧāĻ¤āĻžāĻ° āĻ¸āĻžāĻĨā§, āĻāĻ¯āĻŧā§āĻŦ āĻ¸āĻžāĻ°ā§āĻāĻžāĻ°āĻā§āĻ˛āĻŋāĻā§ āĻāĻāĻ āĻ¸āĻžāĻĨā§ āĻĒā§āĻ°āĻā§āĻ° āĻ¸āĻāĻā§āĻ¯āĻ āĻ¸āĻāĻ¯ā§āĻ āĻĒāĻ°āĻŋāĻāĻžāĻ˛āĻ¨āĻž āĻāĻ°āĻžāĻ° āĻĒā§āĻ°āĻ¯āĻŧā§āĻāĻ¨ āĻšāĻ¤ā§ āĻļā§āĻ°ā§ āĻāĻ°ā§, āĻāĻŦāĻ āĻ¤āĻžāĻ āĻĻā§āĻāĻŋ āĻĒāĻĻā§āĻ§āĻ¤āĻŋāĻ° āĻā§āĻˇā§āĻāĻž āĻāĻ°āĻž āĻšāĻ¯āĻŧā§āĻāĻŋāĻ˛: āĻĒā§āĻ°āĻā§āĻ° āĻ¸āĻāĻā§āĻ¯āĻ OS āĻĨā§āĻ°ā§āĻĄā§ I/O āĻŦā§āĻ˛āĻ āĻāĻ°āĻž āĻāĻŦāĻ I/O-āĻāĻ° āĻ¸āĻžāĻĨā§ āĻāĻāĻ¤ā§āĻ°ā§ āĻŦā§āĻ˛āĻ āĻāĻ°āĻž āĻ¨āĻ¯āĻŧ āĻāĻāĻāĻŋ āĻāĻā§āĻ¨ā§āĻ āĻŦāĻŋāĻā§āĻāĻĒā§āĻ¤āĻŋ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ, āĻ¯āĻžāĻā§ "āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻ¨āĻŋāĻ°ā§āĻŦāĻžāĻāĻ"āĻ āĻŦāĻ˛āĻž āĻšāĻ¯āĻŧ (
āĻĒā§āĻ°āĻĨāĻŽ āĻĒāĻĻā§āĻ§āĻ¤āĻŋāĻ¤ā§ āĻĒā§āĻ°āĻ¤āĻŋāĻāĻŋ āĻāĻāĻ¤ āĻ¸āĻāĻ¯ā§āĻā§āĻ° āĻāĻ¨ā§āĻ¯ āĻāĻāĻāĻŋ āĻ¨āĻ¤ā§āĻ¨ OS āĻĨā§āĻ°ā§āĻĄ āĻ¤ā§āĻ°āĻŋ āĻāĻ°āĻž āĻāĻĄāĻŧāĻŋāĻ¤āĨ¤ āĻāĻ° āĻ
āĻ¸ā§āĻŦāĻŋāĻ§āĻž āĻšāĻ˛ āĻĻā§āĻ°ā§āĻŦāĻ˛ āĻŽāĻžāĻĒāĻ¯ā§āĻā§āĻ¯āĻ¤āĻž: āĻ
āĻĒāĻžāĻ°ā§āĻāĻŋāĻ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽāĻā§ āĻ
āĻ¨ā§āĻāĻā§āĻ˛āĻŋ āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨ āĻāĻ°āĻ¤ā§ āĻšāĻŦā§
āĻĒāĻ°āĻŋāĻŦāĻ°ā§āĻ¤āĻŋāĻ¤ āĻ¸āĻāĻ¸ā§āĻāĻ°āĻŖ āĻšāĻžāĻāĻ˛āĻžāĻāĻ
āĻĻā§āĻŦāĻŋāĻ¤ā§āĻ¯āĻŧ āĻĒāĻĻā§āĻ§āĻ¤āĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°ā§
āĻāĻ āĻĒāĻĻā§āĻ§āĻ¤āĻŋāĻ° āĻŽāĻ§ā§āĻ¯ā§ āĻĒāĻžāĻ°ā§āĻĨāĻā§āĻ¯ āĻ¨āĻŋāĻŽā§āĻ¨āĻ°ā§āĻĒ:
- I/O āĻ
āĻĒāĻžāĻ°ā§āĻļāĻ¨ āĻŦā§āĻ˛āĻ āĻāĻ°āĻž āĻ¸ā§āĻĨāĻāĻŋāĻ¤ āĻāĻ°āĻž āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ°āĻāĻžāĻ°ā§ āĻĒā§āĻ°āĻŦāĻžāĻš āĻĒāĻ°ā§āĻ¯āĻ¨ā§āĻ¤OS āĻ¸āĻ āĻŋāĻāĻāĻžāĻŦā§ āĻ¨āĻž āĻšāĻāĻ¯āĻŧāĻž āĻĒāĻ°ā§āĻ¯āĻ¨ā§āĻ¤
āĻĄāĻŋāĻĢā§āĻ°ā§āĻ¯āĻžāĻāĻŽā§āĻ¨ā§āĻāĻ¸ āĻāĻ¨āĻāĻžāĻŽāĻŋāĻāĻāĻāĻĒāĻŋ āĻĒā§āĻ¯āĻžāĻā§āĻ āĻŦāĻžāĻāĻ āĻ¸ā§āĻā§āĻ°āĻŋāĻŽ āĻāĻ°āĻ¤ā§ (āĻŦāĻŋāĻāĻŋāĻ¨ā§āĻ¨ TCP , āĻĄā§āĻāĻž āĻā§āĻ°āĻšāĻŖ āĻāĻ°āĻž) āĻ āĻĨāĻŦāĻž āĻĒāĻ°āĻŦāĻ°ā§āĻ¤ā§āĻ¤ā§ āĻĒāĻžāĻ āĻžāĻ¨ā§āĻ° āĻāĻ¨ā§āĻ¯ āĻ āĻā§āĻ¯āĻ¨ā§āĻ¤āĻ°ā§āĻŖ āĻ˛ā§āĻāĻžāĻ° āĻŦāĻžāĻĢāĻžāĻ°āĻā§āĻ˛āĻŋāĻ¤ā§ āĻĒāĻ°ā§āĻ¯āĻžāĻĒā§āĻ¤ āĻāĻžāĻ¯āĻŧāĻāĻž āĻĒāĻžāĻāĻ¯āĻŧāĻž āĻ¯āĻžāĻŦā§ āĻ¨āĻžāĻāĻŋāĻā§āĻ (āĻĄā§āĻāĻž āĻĒāĻžāĻ āĻžāĻ¨ā§)āĨ¤ - āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻ¨āĻŋāĻ°ā§āĻŦāĻžāĻāĻ āĻ¸āĻŽāĻ¯āĻŧā§āĻ° āĻ¸āĻžāĻĨā§ āĻ¸āĻžāĻĨā§ āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽāĻā§ āĻ āĻŦāĻšāĻŋāĻ¤ āĻāĻ°ā§ āĻ¯ā§ OS āĻāĻ¤āĻŋāĻŽāĻ§ā§āĻ¯ā§ āĻĄāĻŋāĻĢā§āĻ°ā§āĻ¯āĻžāĻāĻŽā§āĻ¨ā§āĻā§āĻĄ āĻāĻāĻĒāĻŋ āĻĒā§āĻ¯āĻžāĻā§āĻ (āĻāĻŋāĻ¸āĻŋāĻĒāĻŋ, āĻĄā§āĻāĻž āĻ°āĻŋāĻ¸ā§āĻĒāĻļāĻ¨) āĻŦāĻž āĻ āĻā§āĻ¯āĻ¨ā§āĻ¤āĻ°ā§āĻŖ āĻ˛ā§āĻāĻžāĻ° āĻŦāĻžāĻĢāĻžāĻ°āĻā§āĻ˛āĻŋāĻ¤ā§ āĻ¯āĻĨā§āĻˇā§āĻ āĻāĻžāĻ¯āĻŧāĻāĻž āĻāĻ¤āĻŋāĻŽāĻ§ā§āĻ¯ā§ āĻāĻĒāĻ˛āĻŦā§āĻ§ (āĻĄā§āĻāĻž āĻĒāĻžāĻ āĻžāĻ¨ā§)āĨ¤
āĻ¸āĻāĻā§āĻˇā§āĻĒā§ āĻŦāĻ˛āĻ¤ā§ āĻā§āĻ˛ā§, āĻĒā§āĻ°āĻ¤āĻŋāĻāĻŋ I/O-āĻāĻ° āĻāĻ¨ā§āĻ¯ āĻāĻāĻāĻŋ OS āĻĨā§āĻ°ā§āĻĄ āĻ¸āĻāĻ°āĻā§āĻˇāĻŖ āĻāĻ°āĻž āĻāĻŽā§āĻĒāĻŋāĻāĻāĻŋāĻ āĻļāĻā§āĻ¤āĻŋāĻ° āĻ
āĻĒāĻāĻ¯āĻŧ, āĻāĻžāĻ°āĻŖ āĻŦāĻžāĻ¸ā§āĻ¤āĻŦā§, āĻĨā§āĻ°ā§āĻĄāĻā§āĻ˛āĻŋ āĻāĻžāĻ°ā§āĻ¯āĻāĻ° āĻāĻžāĻ āĻāĻ°āĻā§ āĻ¨āĻž (āĻ
āĻ¤āĻāĻŦ āĻļāĻŦā§āĻĻāĻāĻŋ
I/O āĻā§āĻ˛ā§āĻ˛āĻŋ āĻŽāĻĄā§āĻ˛
I/O āĻā§āĻ˛ā§āĻ˛āĻŋ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻ¨āĻŋāĻ°ā§āĻŦāĻžāĻāĻ āĻāĻŦāĻ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ°āĻāĻžāĻ°ā§ āĻā§āĻĄā§āĻ° āĻŽāĻ§ā§āĻ¯ā§ āĻāĻāĻāĻŋ āĻ¸ā§āĻ¤āĻ° āĻšāĻŋāĻ¸āĻžāĻŦā§ āĻāĻžāĻ āĻāĻ°ā§āĨ¤ āĻāĻ° āĻ āĻĒāĻžāĻ°ā§āĻļāĻ¨ā§āĻ° āĻ¨ā§āĻ¤āĻŋāĻāĻŋ āĻ¨āĻŋāĻŽā§āĻ¨āĻ˛āĻŋāĻāĻŋāĻ¤ āĻŦā§āĻ˛āĻ āĻĄāĻžāĻ¯āĻŧāĻžāĻā§āĻ°āĻžāĻŽ āĻĻā§āĻŦāĻžāĻ°āĻž āĻŦāĻ°ā§āĻŖāĻŋāĻ¤ āĻšāĻ¯āĻŧā§āĻā§:
- āĻāĻŽāĻŋ āĻāĻĒāĻ¨āĻžāĻā§ āĻŽāĻ¨ā§ āĻāĻ°āĻŋāĻ¯āĻŧā§ āĻĻāĻŋāĻ āĻ¯ā§ āĻāĻāĻāĻŋ āĻāĻā§āĻ¨ā§āĻ āĻšāĻ˛ āĻāĻāĻāĻŋ āĻŦāĻŋāĻā§āĻāĻĒā§āĻ¤āĻŋ āĻ¯ā§ āĻāĻāĻāĻŋ āĻ¨āĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āĻ āĻ¸āĻā§āĻ āĻāĻāĻāĻŋ āĻ¨āĻ¨-āĻŦā§āĻ˛āĻāĻŋāĻ I/O āĻ āĻĒāĻžāĻ°ā§āĻļāĻ¨ āĻāĻ°āĻ¤ā§ āĻ¸āĻā§āĻˇāĻŽāĨ¤
- āĻāĻāĻāĻŋ āĻāĻā§āĻ¨ā§āĻ āĻšā§āĻ¯āĻžāĻ¨ā§āĻĄāĻ˛āĻžāĻ° āĻšāĻ˛ āĻāĻāĻāĻŋ āĻĢāĻžāĻāĻļāĻ¨ āĻ¯āĻžāĻā§ I/O āĻā§āĻ˛ā§āĻ˛āĻŋ āĻĻā§āĻŦāĻžāĻ°āĻž āĻĄāĻžāĻāĻž āĻšāĻ¯āĻŧ āĻ¯āĻāĻ¨ āĻāĻāĻāĻŋ āĻāĻā§āĻ¨ā§āĻ āĻĒā§āĻ°āĻžāĻĒā§āĻ¤ āĻšāĻ¯āĻŧ, āĻ¯āĻž āĻĒāĻ°ā§ āĻāĻāĻāĻŋ āĻ -āĻŦā§āĻ˛āĻāĻŋāĻ I/O āĻ āĻĒāĻžāĻ°ā§āĻļāĻ¨ āĻ¸āĻŽā§āĻĒāĻžāĻĻāĻ¨ āĻāĻ°ā§āĨ¤
āĻāĻāĻŋ āĻ˛āĻā§āĻˇ āĻāĻ°āĻž āĻā§āĻ°ā§āĻ¤ā§āĻŦāĻĒā§āĻ°ā§āĻŖ āĻ¯ā§ I/O āĻā§āĻ˛ā§āĻ˛āĻŋāĻāĻŋ āĻ¸āĻāĻā§āĻāĻž āĻ āĻ¨ā§āĻ¸āĻžāĻ°ā§ āĻāĻāĻ-āĻĨā§āĻ°ā§āĻĄā§āĻĄ, āĻ¤āĻŦā§ āĻ§āĻžāĻ°āĻŖāĻžāĻāĻŋāĻā§ 1 āĻĨā§āĻ°ā§āĻĄ: 1 āĻ°āĻŋāĻ ā§āĻ¯āĻžāĻā§āĻāĻ°ā§āĻ° āĻ āĻ¨ā§āĻĒāĻžāĻ¤ā§ āĻŦāĻšā§-āĻĨā§āĻ°ā§āĻĄā§āĻĄ āĻĒāĻ°āĻŋāĻŦā§āĻļā§ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°āĻž āĻĨā§āĻā§ āĻŦāĻŋāĻ°āĻ¤ āĻāĻ°āĻžāĻ° āĻāĻŋāĻā§ āĻ¨ā§āĻ, āĻ¯āĻžāĻ° āĻĢāĻ˛ā§ āĻ¸āĻŽāĻ¸ā§āĻ¤ 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 āĻā§āĻ˛ā§āĻ˛āĻŋ āĻāĻ āĻ¨ āĻāĻ āĻŋāĻ¤ GHashTable
CallbackData
(āĻāĻāĻāĻŋ āĻāĻā§āĻ¨ā§āĻ āĻšā§āĻ¯āĻžāĻ¨ā§āĻĄāĻ˛āĻžāĻ°ā§āĻ° āĻāĻžāĻ āĻžāĻŽā§ āĻāĻŦāĻ āĻāĻāĻŋāĻ° āĻāĻ¨ā§āĻ¯ āĻāĻāĻāĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ°āĻāĻžāĻ°ā§āĻ° āĻ¯ā§āĻā§āĻ¤āĻŋ)āĨ¤
āĻ°āĻŋāĻ ā§āĻ¯āĻžāĻā§āĻāĻ° āĻāĻŦāĻ āĻāĻ˛āĻŦā§āĻ¯āĻžāĻāĻĄā§āĻāĻž āĻĻā§āĻāĻžāĻ¨
struct reactor {
int epoll_fd;
GHashTable *table; // (int, CallbackData)
};
typedef struct {
Callback callback;
void *arg;
} CallbackData;
āĻĻāĻ¯āĻŧāĻž āĻāĻ°ā§ āĻŽāĻ¨ā§ āĻ°āĻžāĻāĻŦā§āĻ¨ āĻ¯ā§ āĻāĻŽāĻ°āĻž āĻĒāĻ°āĻŋāĻāĻžāĻ˛āĻ¨āĻž āĻāĻ°āĻžāĻ° āĻā§āĻˇāĻŽāĻ¤āĻž āĻ¸āĻā§āĻˇāĻŽ āĻāĻ°ā§āĻāĻŋ reactor.h
āĻāĻŽāĻ°āĻž āĻāĻ āĻ¨ āĻā§āĻˇāĻŖāĻž reactor
āĻāĻŦāĻ āĻŽāĻ§ā§āĻ¯ā§ reactor.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;
}
āĻ¸āĻāĻā§āĻˇā§āĻĒā§, āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ°āĻāĻžāĻ°ā§ āĻā§āĻĄā§ āĻĢāĻžāĻāĻļāĻ¨ āĻāĻ˛ā§āĻ° āĻā§āĻāĻ¨ āĻ¨āĻŋāĻŽā§āĻ¨āĻ˛āĻŋāĻāĻŋāĻ¤ āĻĢāĻ°ā§āĻŽāĻāĻŋ āĻā§āĻ°āĻšāĻŖ āĻāĻ°āĻŦā§:
āĻāĻāĻ āĻĨā§āĻ°ā§āĻĄā§āĻĄ āĻ¸āĻžāĻ°ā§āĻāĻžāĻ°
āĻāĻā§āĻ āĻ˛ā§āĻĄā§āĻ° āĻ āĻ§ā§āĻ¨ā§ I/O āĻā§āĻ˛ā§āĻ˛āĻŋ āĻĒāĻ°ā§āĻā§āĻˇāĻž āĻāĻ°āĻžāĻ° āĻāĻ¨ā§āĻ¯, āĻāĻŽāĻ°āĻž āĻāĻāĻāĻŋ āĻ¸āĻžāĻ§āĻžāĻ°āĻŖ HTTP āĻāĻ¯āĻŧā§āĻŦ āĻ¸āĻžāĻ°ā§āĻāĻžāĻ° āĻ˛āĻŋāĻāĻŦ āĻ¯āĻž āĻāĻāĻāĻŋ āĻāĻŋāĻ¤ā§āĻ° āĻ¸āĻš āĻ¯ā§āĻā§āĻ¨ā§ āĻ āĻ¨ā§āĻ°ā§āĻ§ā§ āĻ¸āĻžāĻĄāĻŧāĻž āĻĻā§āĻ¯āĻŧāĨ¤
HTTP āĻĒā§āĻ°ā§āĻā§āĻāĻ˛ā§āĻ° āĻāĻāĻāĻŋ āĻĻā§āĻ°ā§āĻ¤ āĻ°ā§āĻĢāĻžāĻ°ā§āĻ¨ā§āĻ¸
HTTP āĻ¸āĻšāĻā§ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°āĻž āĻ¯ā§āĻ¤ā§ āĻĒāĻžāĻ°ā§
āĻŦāĻŋāĻ¨ā§āĻ¯āĻžāĻ¸ āĻ āĻ¨ā§āĻ°ā§āĻ§
<ĐĐĐĐĐĐĐ> <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 āĻĒā§āĻ°ā§āĻā§āĻāĻ˛ā§āĻ° āĻ¸āĻāĻ¸ā§āĻāĻ°āĻŖ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
(āĻ°āĻŋāĻāĻžāĻ°ā§āĻ¨ āĻĄā§āĻāĻž āĻāĻžāĻāĻĒ)āĨ¤<ĐĐĐĐĐĢĐ>
- āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ°āĻāĻžāĻ°ā§āĻ° āĻĻā§āĻŦāĻžāĻ°āĻž āĻ āĻ¨ā§āĻ°ā§āĻ§ āĻāĻ°āĻž āĻĄā§āĻāĻžāĨ¤ āĻāĻŽāĻžāĻĻā§āĻ° āĻā§āĻˇā§āĻ¤ā§āĻ°ā§, āĻāĻāĻŋ āĻāĻŽā§āĻā§āĻ° āĻĒāĻĨāĻāĻāĻāĻāĻŋāĻāĻŽāĻāĻ˛ .
āĻĢāĻžāĻāĻ˛ http_server.c
common.h
āĻĢāĻžāĻāĻļāĻ¨ āĻĒā§āĻ°ā§āĻā§āĻāĻžāĻāĻĒ āĻĻā§āĻāĻžāĻ¨ 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()
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()
āĻ āĻ¨_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()
, āĻĄā§āĻāĻž āĻĒāĻžāĻ āĻžāĻ¨ā§āĻ° āĻāĻ¨ā§āĻ¯ āĻĒā§āĻ°āĻ¸ā§āĻ¤ā§āĻ¤āĨ¤ āĻāĻ āĻĢāĻžāĻāĻļāĻ¨āĻāĻŋ āĻā§āĻ˛āĻžāĻ¯āĻŧā§āĻ¨ā§āĻāĻā§ āĻāĻāĻāĻŋ āĻāĻŋāĻ¤ā§āĻ° āĻ¸āĻš HTML āĻ¸āĻš āĻāĻāĻāĻŋ HTTP āĻĒā§āĻ°āĻ¤āĻŋāĻā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻĒāĻžāĻ āĻžāĻ¯āĻŧ āĻāĻŦāĻ āĻ¤āĻžāĻ°āĻĒāĻ°ā§ āĻāĻā§āĻ¨ā§āĻ āĻšā§āĻ¯āĻžāĻ¨ā§āĻĄāĻ˛āĻžāĻ°āĻā§ āĻāĻŦāĻžāĻ° āĻĒāĻ°āĻŋāĻŦāĻ°ā§āĻ¤āĻ¨ āĻāĻ°ā§ 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
āĻĒā§āĻ°āĻā§āĻā§āĻ āĻ°ā§āĻā§) āĻāĻŦāĻ āĻ¸ā§āĻŦ-āĻ˛āĻŋāĻāĻŋāĻ¤ āĻ¸āĻžāĻ°ā§āĻāĻžāĻ° āĻāĻžāĻ˛ā§ āĻāĻ°ā§āĻ¨, āĻā§āĻ˛ā§āĻ¨
āĻāĻ°ā§āĻŽāĻā§āĻˇāĻŽāĻ¤āĻž āĻĒāĻ°āĻŋāĻŽāĻžāĻĒ
āĻāĻŽāĻžāĻ° āĻāĻžāĻĄāĻŧāĻŋāĻ° āĻ¸ā§āĻĒā§āĻ¸āĻŋāĻĢāĻŋāĻā§āĻļāĻ¨ āĻĻā§āĻāĻžāĻ¨
$ 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 -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 āĻā§āĻ˛ā§āĻ˛āĻŋ āĻāĻ˛āĻžāĻĻāĻž āĻĨā§āĻ°ā§āĻĄā§ āĻ¤ā§āĻ°āĻŋ āĻāĻ°āĻž āĻ¯ā§āĻ¤ā§ āĻĒāĻžāĻ°ā§, āĻ¯āĻžāĻ° āĻĢāĻ˛ā§ āĻ¸āĻŽāĻ¸ā§āĻ¤ 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
-march=native
, 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 āĻŽāĻŋāĻ¨āĻŋāĻā§ āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻā§āĻ¤ āĻ āĻ¨ā§āĻ°ā§āĻ§ā§āĻ° āĻ¸āĻāĻā§āĻ¯āĻžāĻ° āĻ¨āĻŋāĻ°ā§āĻāĻ°āĻ¤āĻž āĻĻā§āĻāĻžāĻ¯āĻŧ:
āĻāĻŽāĻ°āĻž āĻĻā§āĻāĻ¤ā§ āĻĒāĻžāĻā§āĻāĻŋ āĻ¯ā§ āĻāĻ¯āĻŧā§āĻāĻļā§ āĻ¸āĻāĻ¯ā§āĻā§āĻ° āĻĒāĻ°ā§, āĻāĻāĻ¯āĻŧ āĻ¸āĻžāĻ°ā§āĻāĻžāĻ°ā§āĻ° āĻāĻ¨ā§āĻ¯ āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻā§āĻ¤ āĻ āĻ¨ā§āĻ°ā§āĻ§ā§āĻ° āĻ¸āĻāĻā§āĻ¯āĻž āĻĻā§āĻ°ā§āĻ¤ āĻšā§āĻ°āĻžāĻ¸ āĻĒāĻžāĻ¯āĻŧ (āĻŽāĻžāĻ˛ā§āĻāĻŋ-āĻĨā§āĻ°ā§āĻĄā§āĻĄ āĻ¸āĻāĻ¸ā§āĻāĻ°āĻŖā§ āĻāĻāĻŋ āĻāĻ°āĻ āĻ˛āĻā§āĻˇāĻŖā§āĻ¯āĻŧ)āĨ¤ āĻāĻāĻŋ āĻāĻŋ āĻ˛āĻŋāĻ¨āĻžāĻā§āĻ¸ āĻāĻŋāĻ¸āĻŋāĻĒāĻŋ/āĻāĻāĻĒāĻŋ āĻ¸ā§āĻā§āĻ¯āĻžāĻ āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨ā§āĻ° āĻ¸āĻžāĻĨā§ āĻ¸āĻŽā§āĻĒāĻ°ā§āĻāĻŋāĻ¤? āĻŽāĻ¨ā§āĻ¤āĻŦā§āĻ¯ā§ āĻŦāĻšā§-āĻĨā§āĻ°ā§āĻĄā§āĻĄ āĻāĻŦāĻ āĻāĻāĻ-āĻĨā§āĻ°ā§āĻĄā§āĻĄ āĻŦāĻŋāĻāĻ˛ā§āĻĒāĻā§āĻ˛āĻŋāĻ° āĻāĻ¨ā§āĻ¯ āĻā§āĻ°āĻžāĻĢā§āĻ° āĻāĻ āĻāĻāĻ°āĻŖ āĻāĻŦāĻ āĻ āĻĒā§āĻāĻŋāĻŽāĻžāĻāĻā§āĻļāĻ¨ āĻ¸āĻŽā§āĻĒāĻ°ā§āĻā§ āĻāĻĒāĻ¨āĻžāĻ° āĻ āĻ¨ā§āĻŽāĻžāĻ¨āĻā§āĻ˛āĻŋ āĻ¨āĻŋāĻ°ā§āĻĻā§āĻŦāĻŋāĻ§āĻžāĻ¯āĻŧ āĻ˛āĻŋāĻā§āĻ¨ā§ˇ
āĻāĻŋāĻāĻžāĻŦā§
I/O āĻā§āĻ˛ā§āĻ˛āĻŋāĻ° āĻ āĻ¸ā§āĻŦāĻŋāĻ§āĻž
āĻāĻĒāĻ¨āĻžāĻā§ āĻŦā§āĻāĻ¤ā§ āĻšāĻŦā§ āĻ¯ā§ I/O āĻā§āĻ˛ā§āĻ˛āĻŋāĻāĻŋ āĻ¤āĻžāĻ° āĻ¤ā§āĻ°ā§āĻāĻŋāĻā§āĻ˛āĻŋ āĻāĻžāĻĄāĻŧāĻž āĻ¨āĻ¯āĻŧ, āĻ¯āĻĨāĻž:
- āĻŽāĻžāĻ˛ā§āĻāĻŋ-āĻĨā§āĻ°ā§āĻĄā§āĻĄ āĻĒāĻ°āĻŋāĻŦā§āĻļā§ āĻāĻāĻāĻŋ I/O āĻā§āĻ˛ā§āĻ˛āĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°āĻž āĻāĻŋāĻā§āĻāĻž āĻŦā§āĻļāĻŋ āĻāĻ āĻŋāĻ¨, āĻāĻžāĻ°āĻŖ āĻāĻĒāĻ¨āĻžāĻā§ āĻŽā§āĻ¯āĻžāĻ¨ā§āĻ¯āĻŧāĻžāĻ˛āĻŋ āĻĒā§āĻ°āĻŦāĻžāĻš āĻĒāĻ°āĻŋāĻāĻžāĻ˛āĻ¨āĻž āĻāĻ°āĻ¤ā§ āĻšāĻŦā§āĨ¤
- āĻ āĻ¨ā§āĻļā§āĻ˛āĻ¨ āĻĻā§āĻāĻžāĻ¯āĻŧ āĻ¯ā§ āĻŦā§āĻļāĻŋāĻ°āĻāĻžāĻ āĻā§āĻˇā§āĻ¤ā§āĻ°ā§ āĻ˛ā§āĻĄ āĻ -āĻāĻ¨āĻŋāĻĢāĻ°ā§āĻŽ, āĻ¯āĻžāĻ° āĻĢāĻ˛ā§ āĻāĻāĻāĻŋ āĻĨā§āĻ°ā§āĻĄ āĻ˛āĻāĻŋāĻ āĻšāĻ¤ā§ āĻĒāĻžāĻ°ā§ āĻ¯āĻāĻ¨ āĻ āĻ¨ā§āĻ¯āĻāĻŋ āĻāĻžāĻā§ āĻŦā§āĻ¯āĻ¸ā§āĻ¤ āĻĨāĻžāĻā§āĨ¤
- āĻ¯āĻĻāĻŋ āĻāĻāĻāĻŋ āĻāĻā§āĻ¨ā§āĻ āĻšā§āĻ¯āĻžāĻ¨ā§āĻĄāĻ˛āĻžāĻ° āĻāĻāĻāĻŋ āĻĨā§āĻ°ā§āĻĄ āĻŦā§āĻ˛āĻ āĻāĻ°ā§, āĻ¤āĻŦā§ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻ¨āĻŋāĻ°ā§āĻŦāĻžāĻāĻ āĻ¨āĻŋāĻā§āĻ āĻŦā§āĻ˛āĻ āĻāĻ°āĻŦā§, āĻ¯āĻž āĻā§āĻāĻā§ āĻĒāĻžāĻāĻ¯āĻŧāĻž āĻāĻ āĻŋāĻ¨ āĻŦāĻžāĻāĻā§āĻ˛āĻŋāĻ° āĻĻāĻŋāĻā§ āĻĒāĻ°āĻŋāĻāĻžāĻ˛āĻŋāĻ¤ āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°ā§āĨ¤
āĻāĻ¸āĻŦ āĻ¸āĻŽāĻ¸ā§āĻ¯āĻžāĻ° āĻ¸āĻŽāĻžāĻ§āĻžāĻ¨ āĻāĻ°ā§
āĻāĻĒāĻ¸āĻāĻšāĻžāĻ°
āĻāĻāĻžāĻ¨ā§āĻ āĻ¤āĻ¤ā§āĻ¤ā§āĻŦ āĻĨā§āĻā§ āĻ¸āĻ°āĻžāĻ¸āĻ°āĻŋ āĻĒā§āĻ°ā§āĻĢāĻžāĻāĻ˛āĻžāĻ° āĻāĻā§āĻ¸āĻžāĻ¸ā§āĻā§ āĻāĻŽāĻžāĻĻā§āĻ° āĻ¯āĻžāĻ¤ā§āĻ°āĻž āĻļā§āĻˇ āĻšāĻ¯āĻŧā§āĻā§āĨ¤
āĻāĻĒāĻ¨āĻžāĻ° āĻāĻāĻŋāĻ¤ā§ āĻĨāĻžāĻāĻž āĻāĻāĻŋāĻ¤ āĻ¨āĻ¯āĻŧ, āĻāĻžāĻ°āĻŖ āĻŦāĻŋāĻāĻŋāĻ¨ā§āĻ¨ āĻ¸ā§āĻ¤āĻ°ā§āĻ° āĻ¸ā§āĻŦāĻŋāĻ§āĻž āĻāĻŦāĻ āĻāĻ¤āĻŋ āĻ¸āĻš āĻ¨ā§āĻāĻāĻ¯āĻŧāĻžāĻ°ā§āĻ āĻ¸āĻĢā§āĻāĻāĻ¯āĻŧā§āĻ¯āĻžāĻ° āĻ˛ā§āĻāĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻāĻ°āĻ āĻ āĻ¨ā§āĻāĻā§āĻ˛āĻŋ āĻ¸āĻŽāĻžāĻ¨ āĻāĻāĻ°ā§āĻˇāĻŖā§āĻ¯āĻŧ āĻĒāĻ¨ā§āĻĨāĻž āĻ°āĻ¯āĻŧā§āĻā§āĨ¤ āĻāĻāĻ°ā§āĻˇāĻŖā§āĻ¯āĻŧ, āĻāĻŽāĻžāĻ° āĻŽāĻ¤ā§, āĻ˛āĻŋāĻā§āĻ āĻ¨ā§āĻā§ āĻĻā§āĻāĻ¯āĻŧāĻž āĻšāĻ¯āĻŧ.
ĐŅŅŅĐĩŅ ĐŊОвŅŅ вŅŅŅĐĩŅ!
āĻāĻāĻ°ā§āĻˇāĻŖā§āĻ¯āĻŧ āĻĒā§āĻ°āĻāĻ˛ā§āĻĒ
- āĻŦāĻŋ
āĻāĻ
āĻāĻ° āĻāĻŋ āĻĒāĻĄāĻŧāĻ¤ā§ āĻšāĻŦā§?
https://linux.die.net/man/7/socket https://stackoverflow.com/questions/1050222/what-is-the-difference-between-concurrency-and-parallelism http://www.kegel.com/c10k.html https://kernel.dk/io_uring.pdf https://aturon.github.io/blog/2016/09/07/futures-design/ https://tokio.rs/blog/2019-10-scheduler/ https://www.artima.com/articles/io_design_patterns.html https://habr.com/en/post/183832/
āĻāĻ¤ā§āĻ¸: www.habr.com