win7에서 libevent가 구현한rot13 서버
// libev_rot13.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <event2/event.h>
#include <assert.h>
#define MAX_LINE 16384
void do_read(evutil_socket_t fd, short events, void *arg);
void do_write(evutil_socket_t fd, short events, void *arg);
char rot13_char(char c)
{
if ((c >= 'a' && c <= 'm') || (c >= 'A' && c <= 'M'))
return c + 13;
else if ((c >= 'n' && c <= 'z') || (c >= 'N' && c <= 'Z'))
return c - 13;
else
return c;
}
struct fd_state {
char buffer[MAX_LINE];
size_t buffer_used;
size_t n_written;
size_t write_upto;
struct event *read_event;
struct event *write_event;
};
struct fd_state * alloc_fd_state(struct event_base *base, evutil_socket_t fd)
{
struct fd_state *state = (struct fd_state *)malloc(sizeof(struct fd_state));
if (!state)
return NULL;
state->read_event = event_new(base, fd, EV_READ|EV_PERSIST, do_read, state);
if (!state->read_event) {
free(state);
return NULL;
}
state->write_event = event_new(base, fd, EV_WRITE|EV_PERSIST, do_write, state);
if (!state->write_event) {
event_free(state->read_event);
free(state);
return NULL;
}
state->buffer_used = state->n_written = state->write_upto = 0;
assert(state->write_event);
return state;
}
void free_fd_state(struct fd_state *state)
{
event_free(state->read_event);
event_free(state->write_event);
free(state);
}
void do_read(evutil_socket_t fd, short events, void *arg)
{
struct fd_state *state = (struct fd_state *)arg;
char buf[1024] = {0};
int i;
size_t result = 0;
while (1) {
assert(state->write_event);
result = recv(fd, buf, sizeof(buf), 0);
if (result == SOCKET_ERROR)
break;
for (i=0; i < result; ++i) {
if (state->buffer_used < sizeof(state->buffer))
state->buffer[state->buffer_used++] = rot13_char(buf[i]);
if (buf[i] == '
') {
assert(state->write_event);
event_add(state->write_event, NULL);
state->write_upto = state->buffer_used;
}
}
}
if (result == 0) {
perror("read error");
free_fd_state(state);
} else if (result < 0) {
if (WSAGetLastError() == WSAEWOULDBLOCK) // XXXX use evutil macro
return;
perror("recv");
free_fd_state(state);
}
}
void do_write(evutil_socket_t fd, short events, void *arg)
{
struct fd_state *state = (struct fd_state *)arg;
while (state->n_written < state->write_upto) {
int result = send(fd, state->buffer + state->n_written,
state->write_upto - state->n_written, 0);
if (result == SOCKET_ERROR) {
if (WSAGetLastError() == WSAEWOULDBLOCK) // XXX use evutil macro
return;
free_fd_state(state);
return;
}
assert(result != 0);
state->n_written += result;
}
if (state->n_written == state->buffer_used)
state->n_written = state->write_upto = state->buffer_used = 1;
event_del(state->write_event);
}
void do_accept(evutil_socket_t listener, short event, void *arg)
{
struct event_base *base = (struct event_base *)arg;
struct sockaddr_storage ss;
int slen = sizeof(ss);
int fd = accept(listener, (struct sockaddr*)&ss, &slen);
if (fd == INVALID_SOCKET) {
perror("accept");
} else {
struct fd_state *state;
evutil_make_socket_nonblocking(fd);
state = alloc_fd_state(base, fd);
assert(state);
assert(state->write_event);
event_add(state->read_event, NULL);
}
}
void run(void)
{
evutil_socket_t listener;
struct sockaddr_in sin;
struct event_base *base;
struct event *listener_event;
base = event_base_new();
if (!base)
return;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = 0;
sin.sin_port = htons(40713);
listener = socket(AF_INET, SOCK_STREAM, 0);
evutil_make_socket_nonblocking(listener);
if (bind(listener, (struct sockaddr*)&sin, sizeof(sin)) < 0) {
perror("bind");
return;
}
if (listen(listener, 16)<0) {
perror("listen");
return;
}
listener_event = event_new(base, listener, EV_READ|EV_PERSIST, do_accept, (void*)base);
event_add(listener_event, NULL);
event_base_dispatch(base);
}
int main(int c, char **v)
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return -1;
}
setvbuf(stdout, NULL, _IONBF, 0);
run();
WSACleanup();
return 0;
}
작업 과정
WSAStartup()
event_base_new () 새 이벤트 loop
정탐 소켓을 만들고 vutil_ 호출make_socket_nonblocking, 비차단으로 설정합니다.
bind
listen
event_new 정탐 소켓의 이벤트 대상을 만듭니다. EV_READ|EV_PERSIST 로고 위치는 이벤트 읽기에 관심이 있음을 표시하고listen socket의read callback을 설정합니다.이 콜백에 호출되었을 때, 외부 연결이 왔다는 것을 설명합니다.
event_add는 새로 만든 이벤트 이벤트 대상을 이벤트 루프에 추가합니다.
event_base_dispatch에서 요청을 처리하기 시작합니다.
do_accept 프로세스
accept 연결 수신
evutil_make_socket_nonblocking에서 새 socket을 비차단으로 설정합니다.
새로 받은 socket에 대해read 이벤트와 write 이벤트를 만들고 메모리 영역에서 세션을 저장하는 과정에서 데이터를 분배합니다.
event_add는 socket의read 이벤트를 이벤트 루프에 추가합니다.이 socket가 데이터를 받았을 때do_로 호출됩니다read
do_read 프로세스
recv 수신 데이터
데이터 end까지 데이터를 처리합니다.
event_add는 socket의 write 이벤트를 이벤트 루프에 추가하고response를 다시 보내기 시작합니다.
do_write 프로세스
전송 데이터
event_del 발송이 완료되면 이벤트 루프에서 write 이벤트를 삭제합니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
제한된 크기의 디렉토리를 만드는 방법오늘 저는 장치에 공간이 없을 때 백업 중에 응용 프로그램이 어떻게 작동하는지 테스트(및 수정)하는 작업이 있습니다. 결과적으로 "남은 공간 없음"오류로 백업이 실패하면 새 파일이 없어야 합니다. 지금까지 문제를 재...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.