เชชเชฐเชฟเชเชฏ
Node.js เชเซเชฐ เชเซเชฐเชพเชจเซเชธเชฎเชฟเชถเชจ เชเซเชฐเซเชฎเชฟเชฏเชฎ เชฏเชพเชฆ เชฐเชพเชเซเชฒ - ...
เช เชฒเซเชเชฎเชพเช, เช เชฎเซ I/O เชฐเชฟเชเชเซเชเชฐเชจเชพ เชเชจเซเชธ เช เชจเซ เชเชเชเซเชธ เชเซเชเชถเซเช เช เชจเซ เชคเซ เชเซเชตเซ เชฐเซเชคเซ เชเชพเชฐเซเชฏ เชเชฐเซ เชเซ, เชเซเชกเชจเซ 200 เชฅเซ เชเชเซ เชฒเชพเชเชจเชฎเชพเช เช เชฎเชฒเซเชเชฐเชฃ เชฒเชเซเชถเซเช เช เชจเซ 40 เชฎเชฟเชฒเชฟเชฏเชจ เชตเชฟเชจเชเชคเซเช/เชฎเชฟเชจเชฟเชเชฅเซ เชตเชงเซ เชเช เชธเชฐเชณ HTTP เชธเชฐเซเชตเชฐ เชชเซเชฐเชเซเชฐเชฟเชฏเชพ เชเชฐเซเชถเซเช.
เชซเซเชฐเชตเชฐเซเชก
- เชฒเซเช I/O เชฐเชฟเชเชเซเชเชฐเชจเซ เชเชพเชฎเชเซเชฐเซเชจเซ เชธเชฎเชเชตเชพเชฎเชพเช เชฎเชฆเชฆ เชเชฐเชตเชพ เช เชจเซ เชคเซเชฅเซ เชคเซเชจเซ เชเชชเชฏเซเช เชเชฐเชคเซ เชตเชเชคเซ เชเซเชเชฎเซเชจเซ เชธเชฎเชเชตเชพ เชฎเชพเชเซ เชฒเชเชตเชพเชฎเชพเช เชเชตเซเชฏเซ เชนเชคเซ.
- เชฒเซเชเชจเซ เชธเชฎเชเชตเชพ เชฎเชพเชเซ เชฎเซเชณเชญเซเชค เชฌเชพเชฌเชคเซเชจเซเช เชเซเชเชพเชจ เชเชฐเซเชฐเซ เชเซ.
เชธเซ เชญเชพเชทเชพ เช เชจเซ เชจเซเชเชตเชฐเซเช เชเชชเซเชฒเชฟเชเซเชถเชจ เชกเซเชตเชฒเชชเชฎเซเชจเซเชเชฎเชพเช เชฅเซเชกเซ เช เชจเซเชญเชต. - (เชธเชพเชตเชงเชพเชจ: เชฒเชพเชเชฌเซ PDF)
C11 เชงเซเชฐเชฃ เชธเซเชงเซ Linux เชฎเชพเชเซ เช เชจเซ เชคเซเชจเชพ เชชเชฐ เชเชชเชฒเชฌเซเชง เชเซGitHub .
เชคเชฎเชพเชฐเซ เชคเซเชจเซ เชเซเชฎ เชเชฐเซเชฐ เชเซ?
เชเชจเซเชเชฐเชจเซเชเชจเซ เชตเชงเชคเซ เชเชคเซ เชฒเซเชเชชเซเชฐเชฟเชฏเชคเชพ เชธเชพเชฅเซ, เชตเซเชฌ เชธเชฐเซเชตเชฐเซเชธเชจเซ เชเชเชธเชพเชฅเซ เชฎเซเชเซ เชธเชเชเซเชฏเชพเชฎเชพเช เชเชจเซเชเซเชถเชจเซเชธ เชนเซเชจเซเชกเชฒ เชเชฐเชตเชพเชจเซ เชเชฐเซเชฐ เชชเชกเซ, เช
เชจเซ เชคเซเชฅเซ เชฌเซ เช
เชญเชฟเชเชฎเซ เช
เชเชฎเชพเชตเชตเชพเชฎเชพเช เชเชตเซเชฏเชพ: เชฎเซเชเซ เชธเชเชเซเชฏเชพเชฎเชพเช OS เชฅเซเชฐเซเชกเซ เชชเชฐ I/O เชจเซ เช
เชตเชฐเซเชงเชฟเชค เชเชฐเชตเซเช เช
เชจเซ I/O เชจเซ เช
เชตเชฐเซเชงเชฟเชค เชจ เชเชฐเชตเซเช เชเชตเซเชจเซเช เชธเซเชเชจเชพ เชธเชฟเชธเซเชเชฎ, เชเซเชจเซ "เชธเชฟเชธเซเชเชฎ เชธเชฟเชฒเซเชเซเชเชฐ" เชชเชฃ เชเชนเซเชตเชพเชฏ เชเซ (
เชชเซเชฐเชฅเชฎ เช
เชญเชฟเชเชฎเชฎเชพเช เชฆเชฐเซเช เชเชจเชเชฎเชฟเชเช เชเชจเซเชเซเชถเชจ เชฎเชพเชเซ เชจเชตเซ OS เชฅเซเชฐเซเชก เชฌเชจเชพเชตเชตเชพเชจเซ เชธเชฎเชพเชตเซเชถ เชฅเชพเชฏ เชเซ. เชคเซเชจเซ เชเซเชฐเชฒเชพเชญ เชจเชฌเชณเซ เชฎเชพเชชเชจเซเชฏเชคเชพ เชเซ: เชเชชเชฐเซเชเชฟเชเช เชธเชฟเชธเซเชเชฎเชจเซ เชเชฃเชพ เช
เชฎเชฒเชฎเชพเช เชฎเซเชเชตเชพ เชชเชกเชถเซ
เชธเชเชถเซเชงเชฟเชค เชธเชเชธเซเชเชฐเชฃ เชนเชพเชเชฒเชพเชเชเซเชธ
เชฌเซเชเซ เช
เชญเชฟเชเชฎ เชเชชเชฏเซเช เชเชฐเซ เชเซ
เช เช เชญเชฟเชเชฎเซ เชตเชเซเชเซเชจเซ เชคเชซเชพเชตเชค เชจเซเชเซ เชฎเซเชเชฌ เชเซ:
- I/O เชเชพเชฎเชเซเชฐเซเชจเซ เช
เชตเชฐเซเชงเชฟเชค เชเชฐเซ เชฐเชนเซเชฏเชพ เชเซเช เชธเชธเซเชชเซเชจเซเชก เชตเชชเชฐเชพเชถเชเชฐเซเชคเชพ เชชเซเชฐเชตเชพเชน เชคเซเชฏเชพเช เชธเซเชงเซเชเซเชฏเชพเช เชธเซเชงเซ OS เชฏเซเชเซเชฏ เชฐเซเชคเซ เชจ เชฅเชพเชฏ เชคเซเชฏเชพเช เชธเซเชงเซ
เชกเชฟเชซเซเชฐเซเชเชฎเซเชจเซเชเซเชธ เชเชจเชเชฎเชฟเชเชIP เชชเซเชเซเชเซ เชฌเชพเชเช เชธเซเชเซเชฐเซเชฎ เชฎเชพเชเซ (เชเซเชธเซเชชเซ , เชกเซเชเชพ เชชเซเชฐเชพเชชเซเชค เชเชฐเซ เชฐเชนเซเชฏเซ เชเซ) เช เชฅเชตเชพ เชเชเชคเชฐเชฟเช เชฒเซเชเชจ เชฌเชซเชฐเซเชธเชฎเชพเช เช เชจเซเชเชพเชฎเซ เชฆเซเชตเชพเชฐเชพ เชฎเซเชเชฒเชตเชพ เชฎเชพเชเซ เชชเซเชฐเชคเซ เชเชเซเชฏเชพ เชเชชเชฒเชฌเซเชง เชฐเชนเซเชถเซ เชจเชนเซเชเชเชจเชเชเชธเซ (เชกเซเชเชพ เชฎเซเชเชฒเซ เชฐเชนเซเชฏเซเช เชเซ). - เชธเชฟเชธเซเชเชฎ เชชเชธเชเชฆเชเซเชเชพเชฐ เชธเชฎเชฏ เชเชคเชพเช เชชเซเชฐเซเชเซเชฐเชพเชฎเชจเซ เชธเซเชเชฟเชค เชเชฐเซ เชเซ เชเซ OS เชชเชนเซเชฒเซเชฅเซ เชกเชฟเชซเซเชฐเซเชเชฎเซเชจเซเชเซเชก IP เชชเซเชเซเชเซเชธ (TCP, เชกเซเชเชพ เชฐเชฟเชธเซเชชเซเชถเชจ) เช เชฅเชตเชพ เชเชเชคเชฐเชฟเช เชฒเชเชพเชฃ เชฌเชซเชฐเซเชธเชฎเชพเช เชชเซเชฐเชคเซ เชเชเซเชฏเชพ เชชเชนเซเชฒเซเชฅเซ เชเชชเชฒเชฌเซเชง (เชกเซเชเชพ เชฎเซเชเชฒเชตเชพ).
เชธเชพเชฐเชพเชเชถเชฎเชพเช เชเชนเซเช เชคเซ, เชฆเชฐเซเช 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
.
เชฐเชฟเชเชเซเชเชฐ_เชฐเชจ() เชซเชเชเซเชถเชจ เชฌเชคเชพเชตเซ
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
(เชฐเซเชเชฐเซเชจ เชกเซเชเชพ เชชเซเชฐเชเชพเชฐ).<ะะะะะซะ>
- เชตเชชเชฐเชพเชถเชเชฐเซเชคเชพ เชฆเซเชตเชพเชฐเชพ เชตเชฟเชจเชเชคเซ เชเชฐเชพเชฏเซเชฒ เชกเซเชเชพ. เช เชฎเชพเชฐเชพ เชเชฟเชธเซเชธเชพเชฎเชพเช, เช เชฎเชพเชเชจเซ เชเชฌเซเชจเซ เชฎเชพเชฐเซเช เชเซ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()
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()
, เชกเซเชเชพ เชฎเซเชเชฒเชตเชพ เชฎเชพเชเซ เชคเซเชฏเชพเชฐ เชเซ. เช เชซเชเชเซเชถเชจ เชเซเชฒเชพเชฏเชเชเชจเซ เชเชฎเซเช เชธเชพเชฅเซ 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 เชฎเชฟเชจเชฟเชเชฎเชพเช เชชเซเชฐเชเซเชฐเชฟเชฏเชพ เชเชฐเซเชฒเซ เชตเชฟเชจเชเชคเซเชเชจเซ เชธเชเชเซเชฏเชพเชจเซ เช เชตเชฒเชเชฌเชจ เชฆเชฐเซเชถเชพเชตเชคเซ เชเช เชฐเชธเชชเซเชฐเชฆ เชเซเชฐเชพเชซ:
เช เชฎเซ เชเซเชเช เชเซเช เชเซ เชฌเซ เชธเซ เชเชจเซเชเซเชถเชจเซเชธ เชชเชเซ, เชฌเชเชจเซ เชธเชฐเซเชตเชฐเซเชธ เชฎเชพเชเซเชจเซ เชชเซเชฐเชเซเชฐเชฟเชฏเชพ เชเชฐเซเชฒเซ เชตเชฟเชจเชเชคเซเชเชจเซ เชธเชเชเซเชฏเชพ เชเชกเชชเชฅเซ เชเชเซ เชเชพเชฏ เชเซ (เชฎเชฒเซเชเซ-เชฅเซเชฐเซเชกเซเชก เชธเชเชธเซเชเชฐเชฃเชฎเชพเช เช เชตเชงเซ เชงเซเชฏเชพเชจเชชเชพเชคเซเชฐ เชเซ). เชถเซเช เช Linux TCP/IP เชธเซเชเซเช เช เชฎเชฒเซเชเชฐเชฃ เชธเชพเชฅเซ เชธเชเชฌเชเชงเชฟเชค เชเซ? เชเชฟเชชเซเชชเชฃเซเชเชฎเชพเช เชเซเชฐเชพเชซเชจเซ เช เชตเชฐเซเชคเชฃเซเช เช เชจเซ เชฎเชฒเซเชเชฟ-เชฅเซเชฐเซเชกเซเชก เช เชจเซ เชธเชฟเชเชเชฒ-เชฅเซเชฐเซเชกเซเชก เชตเชฟเชเชฒเซเชชเซ เชฎเชพเชเซ เชเชชเซเชเชฟเชฎเชพเชเชเซเชถเชจ เชตเชฟเชถเซ เชคเชฎเชพเชฐเซ เชงเชพเชฐเชฃเชพเช เชฒเชเชตเชพ เชฎเชพเชเซ เชจเชฟเชเชธเชเชเซเช.
เชเซเชตเซ เชฐเซเชคเซ
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