เบเบฒเบเบเปเบฒเบชเบฐเปเบซเบเบต
เปเบเบเบปเบเบเบงเบฒเบกเบเบตเป, เบเบงเบเปเบฎเบปเบฒเบเบฐเปเบเบดเปเบ ins เปเบฅเบฐ outs เบเบญเบเปเบเบทเปเบญเบเบเบฐเบเบดเบเบญเบ I / O เปเบฅเบฐเบงเบดเบเบตเบเบฒเบเปเบฎเบฑเบเบงเบฝเบ, เบเบฝเบเบเบฒเบเบเบฐเบเบดเบเบฑเบเปเบเบฅเบฐเบซเบฑเบเบซเบเปเบญเบเบเบงเปเบฒ 200 เปเบชเบฑเปเบ, เปเบฅเบฐเปเบฎเบฑเบเปเบซเปเบเบฐเบเบงเบเบเบฒเบ HTTP server เบเปเบฒเบเบเบฒเบเบซเบผเบฒเบเบเบงเปเบฒ 40 เบฅเปเบฒเบเบเปเบฒเบฎเปเบญเบเบเป / เบเบฒเบเบต.
เบเปเบฒเบญเบฐเบเบดเบเบฒเบ
- เบเบปเบเบเบงเบฒเบกเบเบทเบเบเบฝเบเปเบเบทเปเบญเบเปเบงเบเปเบซเปเปเบเบปเปเบฒเปเบเปเบเบดเบเบเบฒเบเปเบฎเบฑเบเบงเบฝเบเบเบญเบเปเบเบทเปเบญเบเบเบฐเบเบดเบเบญเบ I/O, เปเบฅเบฐเบเบฑเปเบเบเบฑเปเบเบเบดเปเบเปเบเบปเปเบฒเปเบเบเบงเบฒเบกเบชเปเบฝเบเปเบเปเบงเบฅเบฒเบเบตเปเปเบเปเบกเบฑเบ.
- เบเบงเบฒเบกเบฎเบนเปเบเบทเปเบเบเบฒเบเปเบกเปเบเบเปเบฒเปเบเบฑเบเปเบเบทเปเบญเปเบเบปเปเบฒเปเบเบเบปเบเบเบงเบฒเบก.
เบเบฒเบชเบฒ C เปเบฅเบฐเบเบฐเบชเบปเบเบเบฒเบเบเบฒเบเบขเปเบฒเบเปเบเบเบฒเบเบเบฑเบเบเบฐเบเบฒเปเบญเบฑเบเบเบฅเบดเปเบเบเบฑเบเปเบเบทเบญเบเปเบฒเบ. - เบฅเบฐโเบซเบฑเบโเบเบฑเบโเบซเบกเบปเบโเปเบกเปเบโเบเบฝเบโเปเบเบฑเบโเบเบฒโเบชเบฒ C เบขเปเบฒเบโเปเบเบฑเปเบกโเบเบงเบโเบญเบตเบโเบเบฒเบก (เบเปเปเบเบงเบเบฅเบฐเบงเบฑเบ: PDF เบเบฒเบง)
เบเบฑเบเบกเบฒเบเบเบฐเบเบฒเบ C11 เบชเปเบฒเบฅเบฑเบ Linux เปเบฅเบฐเบกเบตเบขเบนเปเปเบGitHub .
เปเบเบฑเบเบซเบเบฑเบเบเบถเปเบเบเปเบฒเปเบเบฑเบ?
เบเปเบงเบเบเบงเบฒเบกเบเบดเบเบปเบกเบเบญเบเบญเบดเบเปเบเบตเปเบเบฑเบเบเบตเปเปเบเบตเปเบกเบเบถเปเบ, เปเบเบทเปเบญเบเปเบกเปเบเปเบฒเบเปเบงเบฑเบเปเบฅเบตเปเบกเบเปเบฒเปเบเบฑเบเบเปเบญเบเบเบฑเบเบเบฒเบเบเบฑเบเบเบฒเบเปเบเบทเปเบญเบกเบเปเปเบเปเบฒเบเบงเบเบซเบฅเบฒเบเบเปเบญเบกเปเบเบฑเบ, เปเบฅเบฐเบเบฑเปเบเบเบฑเปเบเบชเบญเบเบงเบดเบเบตเปเบเปเบเบทเบเบเบฐเบเบฒเบเบฒเบก: เบเบฒเบเบชเบฐเบเบฑเบ I / O เปเบเบเปเบฒเบเบงเบเบซเบฅเบฒเบเบเบญเบ OS threads เปเบฅเบฐ I / O เบเบตเปเบเปเปเบเบดเบเบเบฑเปเบเบเบฐเบชเบปเบกเบเบฐเบชเบฒเบเบเบฑเบ. เบฅเบฐเบเบปเบเบเบฒเบเปเบเปเบเปเบเบทเบญเบเปเบซเบเบเบฒเบ, เปเบญเบตเปเบเบงเปเบฒ "เบเบปเบงเปเบฅเบทเบญเบเบฅเบฐเบเบปเบ" (
เบงเบดเบเบตเบเบฒเบเบเปเบฒเบญเบดเบเบเปเบฝเบงเบเปเบญเบเบเบฑเบเบเบฒเบเบชเปเบฒเบเบเบฐเบเบนเป OS เปเบซเบกเปเบชเปเบฒเบฅเบฑเบเปเบเปเบฅเบฐเบเบฒเบเปเบเบทเปเบญเบกเบเปเปเบเบฒเปเบเบปเปเบฒ. เบเปเปเปเบชเบเบเบญเบเบกเบฑเบเปเบกเปเบเบเบฒเบเบเบฑเบเบเบฐเบซเบเบฒเบเบเบตเปเบเปเปเบเบต: เบฅเบฐเบเบปเบเบเบฐเบเบดเบเบฑเบเบเบฒเบเบเบฐเบเปเบญเบเบเบฐเบเบดเบเบฑเบเบซเบผเบฒเบเบขเปเบฒเบ
เบชเบฐเบเบฑเบเบเบฑเบเปเบเปเปเบเปเปเบเบฑเปเบเปเบชเป
เบงเบดเบเบตเบเบฒเบเบเบตเบชเบญเบเปเบเป
เบเบงเบฒเบกเปเบเบเบเปเบฒเบเบฅเบฐเบซเบงเปเบฒเบเบงเบดเบเบตเบเบฒเบเปเบซเบผเบปเปเบฒเบเบตเปเปเบกเปเบเบกเบตเบเบฑเปเบเบเบตเป:
- เบเบฒเบเบเบฑเบเบเบงเบฒเบเบเบฒเบเบเปเบฒเปเบเบตเบเบเบฒเบ I/O เปเบเบฐ เบเบฐเปเบชเบเบนเปเปเบเป เบเบปเบเบเปเบงเบฒเบเบปเบเบเปเบงเบฒ OS เบเบทเบเบเปเบญเบ
defragments เบเบฒเปเบเบปเปเบฒเบเบธเบ IP เบเบฑเบ byte stream (TCP , เบเบฒเบโเบฎเบฑเบโเบเปเปโเบกเบนเบโ) เบซเบผเบทโเบเบฐโเบเปเปโเบกเบตโเบเบทเปเบโเบเบตเปโเบเบฝเบโเบเปโเบเบตเปโเบกเบตโเบขเบนเปโเปเบโเบเบฒเบโเบเบฑเบโเบเบถเบโเบเบฒเบโเบเบฝเบโเบเบฒเบโเปเบโเบชเปเบฒโเบฅเบฑเบโเบเบฒเบโเบชเบปเปเบโเบเปเปโเบกเบฒโเปเบเบโเบเปเบฒเบโเบเบฒเบNIC (เบชเบปเปเบเบเปเปเบกเบนเบ). - เบเบปเบงเปเบฅเบทเบญเบเบฅเบฐเบเบปเบ เบฅเปเบงเบโเปเบงโเบฅเบฒ เปเบเปเบเปเบเบเบเบฒเบเบงเปเบฒ OS เปเบฅเปเบง เบเบธเบ IP defragmented (TCP, เบเบฒเบเบฎเบฑเบเบเปเปเบกเบนเบ) เบซเบผเบทเบเบทเปเบเบเบตเปเบเบฝเบเบเปเปเบ buffers เบเบฝเบเบเบฒเบเปเบ เปเบฅเปเบง เบชเบฒเบกเบฒเบเปเบเปเปเบเป (เบชเบปเปเบเบเปเปเบกเบนเบ).
เปเบเบทเปเบญเบชเบฐเบซเบผเบธเบเบกเบฑเบ, เบเบฒเบเบเบญเบเบเบฐเบเบนเป OS เบชเปเบฒเบฅเบฑเบเปเบเปเบฅเบฐ I / O เปเบกเปเบเปเบชเบเบเบฐเบฅเบฑเบเบเบฒเบเบเบญเบกเบเบดเบงเปเบเบตเป, เปเบเบฒเบฐเบงเปเบฒเปเบเบเบงเบฒเบกเปเบเบฑเบเบเบดเบ, เบเบฐเบเบนเปเบเปเปเปเบเปเปเบฎเบฑเบเบงเบฝเบเบเบตเปเปเบเบฑเบเบเบฐเปเบซเบเบ (เปเบเบฒเบฐเบชเบฐเบเบฑเปเบเบเปเบฒเบชเบฑเบ.
เบฎเบนเบเปเบเบเปเบเบทเปเบญเบเบเบฐเบเบดเบเบญเบ I/O
เปเบเบทเปเบญเบเบเบฐเบเบดเบเบญเบ 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 เบเบฐเบเบญเบเบเปเบงเบ GHashTable
CallbackData
(เปเบเบเบชเปเบฒเบเบเบญเบเบเบปเบงเบเบฑเบเบเบฒเบเปเบซเบเบเบฒเบเปเบฅเบฐเบเบฒเบเปเบเปเบเบฝเบเบเบญเบเบเบนเปเปเบเปเบชเปเบฒเบฅเบฑเบเบกเบฑเบ).
เบชเบฐเปเบเบ Reactor เปเบฅเบฐ 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
เบเบฑเบเบเบธเบเบเบฑเบเบเบตเบฅเบฒเบเบเบทเปเบเบญเบเปเบเบปเปเบฒเบฎเบฑเบเบเบงเบฒเบกเบชเบปเบเปเบเปเบฅเบฐเบเบปเบงเบเบฑเบเบเบฒเบเปเบซเบเบเบฒเบเบเบตเปเบชเบญเบเบเปเบญเบเบเบฑเบเบขเบนเปเปเบเบเบปเบงเปเบฅเบทเบญเบเบฅเบฐเบเบปเบเปเบฅเบฐเบเบฒเบเบฐเบฅเบฒเบ 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;
}
เปเบเบทเปเบญเบชเบฐเบซเบผเบธเบ, เบฅเบฐเบเบปเบเบเปเบญเบเปเบชเปเบเบฒเบเปเบญเบตเปเบเบเบฑเบเบเบฑเบเปเบเบฅเบฐเบซเบฑเบเบเบนเปเปเบเปเบเบฐเบกเบตเบฎเบนเบเปเบเบเบเบฑเปเบเบเปเปเปเบเบเบตเป:
เปเบเบตเบเปเบงเบตเบเบฐเบเบนเปเบเบฝเบง
เปเบเบทเปเบญเบเบปเบเบชเบญเบเปเบเบทเปเบญเบเบเบฐเบเบดเบเบญเบ 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 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
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()
. 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
เปเบเบฎเบฒเบเปเบเบเบเบฒเบ) เปเบฅเบฐเปเบเบตเบเปเบเบทเปเบญเบเปเบกเปเบเปเบฒเบเบเบตเปเบเบฝเบเบเปเบงเบเบเบปเบเปเบญเบ, เปเบเบตเบ
เบเบฒเบเบงเบฑเบเปเบเบเบเบฐเบชเบดเบเบเบดเบเบฒเบ
เบชเบฐเปเบเบเบชเบฐเปเบเบฒเบฐเบฅเบปเบเบเบญเบเบเปเบญเบ
$ 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 -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
-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 stack เบเป? เบฎเบนเปเบชเบถเบเบเปเปเปเบชเบเบเปเบฒเบเบตเปเบเบฐเบเบฝเบเบชเบปเบกเบกเบธเบเบเบดเบเบฒเบเบเบญเบเบเปเบฒเบเบเปเบฝเบงเบเบฑเบเบเบถเบเบเบดเบเปเบฒเบเบตเปเบเบญเบเบเบฒเบเปเบฅเบฐเบเบฒเบเปเบเบตเปเบกเบเบฐเบชเบดเบเบเบดเบเบฒเบเบชเปเบฒเบฅเบฑเบเบเบฒเบเปเบฅเบทเบญเบเบซเบผเบฒเบเบเบฐเบเบนเปเปเบฅเบฐเบเบฐเบเบนเปเบเบฝเบงเปเบเบเปเบฒเปเบซเบฑเบ.
เบงเบดโเบเบตโเบเบฒเบ
เบเปเปเปเบชเบเบเบญเบเปเบเบทเปเบญเบเบเบฐเบเบดเบเบญเบ I/O
เบเปเบฒเบเบเปเบฒเปเบเบฑเบเบเปเบญเบเปเบเบปเปเบฒเปเบเบงเปเบฒ I/O reactor เบเปเปเปเบกเปเบเบเปเปเบกเบตเบเปเปเบเบปเบเบเปเบญเบเบเบญเบเบกเบฑเบ, เบเบท:
- เบเบฒเบเปเบเปเปเบเบปเบฒเบเบฐเบเบดเบเบญเบ I/O เปเบเบชเบฐเบเบฒเบเปเบงเบเบฅเปเบญเบกเบซเบผเบฒเบเบเบฐเบเบนเปเปเบกเปเบเบกเบตเบเบงเบฒเบกเบซเบเบธเปเบเบเบฒเบเบซเบผเบฒเบ, เปเบเบฒเบฐเบงเปเบฒ เบเปเบฒเบเบเบฐเบเปเบญเบเบเบฑเบเบเบฒเบเบเบฒเบเปเบซเบผเปเบเบปเปเบฒเบเปเบงเบเบเบปเบเปเบญเบ.
- เบเบฒเบเบเบฐเบเบดเบเบฑเบเบชเบฐเปเบเบเปเบซเปเปเบซเบฑเบเบงเปเบฒเปเบเบเปเบฅเบฐเบเบตเบซเบผเบฒเบเบเบตเปเบชเบธเบ, เบเบฒเบเปเบซเบผเบเปเบกเปเบเบเปเปเปเบเบฑเบเปเบญเบเบฐเบเบฒเบ, เปเบเบดเปเบเบชเบฒเบกเบฒเบเบเปเบฒเปเบเบชเบนเปเบเบฒเบเบเบฑเบเปเบกเปเปเบชเบฑเปเบเบซเบเบถเปเบเปเบเบเบฐเบเบฐเบเบตเปเบเบปเบเบญเบทเปเบเบเปเบฒเบฅเบฑเบเบซเบเบธเปเบเบเบฑเบเบงเบฝเบ.
- เบเปเบฒเบเบปเบงเบเบฑเบเบเบฒเบเปเบซเบเบเบฒเบเบซเบเบถเปเบเบเบฅเบฑเบญเบเบเบฐเบเบนเป, เบเบปเบงเปเบฅเบทเบญเบเบฅเบฐเบเบปเบเบเบปเบงเบกเบฑเบเปเบญเบเบเบฑเบเบเบฐเบเบฅเบฑเบญเบ, เปเบเบดเปเบเบชเบฒเบกเบฒเบเบเปเบฒเปเบเบชเบนเปเบเบฒเบเบเบฒเบเบเบตเปเบเบฐเบเบญเบเบซเบฒเบเปเปเบเบปเบเบเปเบญเบ.
เปเบเปเปเบเบเบฑเบเบซเบฒเปเบซเบผเบปเปเบฒเบเบตเป
เบชเบฐเบซเบฅเบธเบ
เบเบตเปเปเบกเปเบเบเปเบญเบเบเบตเปเบเบฒเบเปเบเบตเบเบเบฒเบเบเบญเบเบเบงเบเปเบฎเบปเบฒเบเบฒเบเบเบดเบเบชเบฐเบเบตเปเบเบเบเบปเบเปเบเบปเปเบฒเปเบเปเบเบเปเป profiler เปเบเปเบชเบดเปเบเบชเบธเบเบฅเบปเบ.
เบเปเบฒเบเบเปเปเบเบงเบเบขเบนเปเบเบฑเบเปเบฅเบทเปเบญเบเบเบตเป, เปเบเบฒเบฐเบงเปเบฒเบกเบตเบงเบดเบเบตเบเบฒเบเบญเบทเปเบเปเบเบตเปเบซเบเปเบฒเบชเบปเบเปเบเปเบเบปเปเบฒเบเบฝเบกเบเบฑเบเปเบเบเบฒเบเบเบฝเบเปเบเบผเปเบเบผเบกเปเบเบทเบญเบเปเบฒเบเบเบตเปเบกเบตเบฅเบฐเบเบฑเบเบเบงเบฒเบกเบชเบฐเบเบงเบเบชเบฐเบเบฒเบเปเบฅเบฐเบเบงเบฒเบกเปเบงเบเบตเปเปเบเบเบเปเบฒเบเบเบฑเบ. เบซเบเปเบฒเบชเบปเบเปเบ, เปเบเบเบงเบฒเบกเบเบดเบเปเบซเบฑเบเบเบญเบเบเปเบญเบ, เบเบฒเบเปเบเบทเปเบญเบกเบเปเปเปเบกเปเบเปเบซเปเบเปเบฒเบเบฅเบธเปเบกเบเบตเป.
ะฝะพะฝะพะฒัั ะฒัััะตั!
เปเบเบเบเบฒเบเบเบตเปเบซเบเปเบฒเบชเบปเบเปเบ
- Si
rust
เบเปเบญเบเบเบงเบเบญเปเบฒเบเบซเบเบฑเบเบญเบตเบ?
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