Libevent R6: Bufferevents: concepts and basics

From 탱이의 잡동사니
Revision as of 14:36, 2 February 2015 by Pchero (talk | contribs) (Created page with " == Overview == 원문은 이곳<ref>http://www.wangafu.net/~nickm/libevent-book/Ref6_bufferevent.html</ref>에서 확인할 수 있다. 때로는 이벤트의 응답을 기...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Overview

원문은 이곳<ref>http://www.wangafu.net/~nickm/libevent-book/Ref6_bufferevent.html</ref>에서 확인할 수 있다.

때로는 이벤트의 응답을 기다리기보다, 버퍼의 일부분을 직접 확인할 수 있는 기능이 필요할 때가 있다. 예를 들어 우리가 데이터를 write 한다면 다음과 순서를 가질 수가 있다.

  • Decide that we want to write some data to a connection; put that data in a buffer.
  • Wait for the connection to become writable.
  • Write as much of the data as we can.
  • Remember how much we wrote, and if we still have more data to write, wait for the connection to become writable again.

This buffered IO pattern is common enough that Libevent provides a generic mechanism for it. A "bufferevent" consists of an underlying transport (like a socket), a read buffer, and a write buffer. Instead of regular events, which give callbacks when the underlying transport is ready to be read or written, a bufferevent invokes its user-supplied callbacks when it has read or written enough data.

There are multiple types of bufferevent that all share a common interface. As of this writing, the following types exist:

  • socket-based bufferevents
A bufferevent that sends and receives data from an underlying stream socket, using the event_* interface as its backend.
  • asynchronous-IO bufferevents
A bufferevent that uses the Windows IOCP interface to send and receive data to an underlying stream socket. (Windows only; experimental.)
  • filtering bufferevents
A bufferevent that processes incoming and outgoing data before passing it to an underlying bufferevent object—for example, to compress or translate data.
  • paired bufferevents
Two bufferevents that transmit data to one another.

현재 bufferevents 인터페이스는 스트림 기반 프로토콜(TCP 같은..)에서만 작동한다. UDP 같은 프로토콜은 후에 추가될 예정이다.

Bufferevents and evbuffers

모든 bufferevent는 input buffer 와 output buffer를 가진다. struct evbuffer 타입이다. write 하고자 하는 데이터가 있다면 output buffer에 입력하고, read 하고 싶은 데이터가 있다면 input buffer 로부터 읽어 들이면 된다.

Callbacks and watermarks

모든 bufferevent 는 data-related read/write 콜백을 가진다. 기본적으로, read 콜백은 어떤때든지 데이터를 read 할 때 호출되고, write 콜백은 데이터를 write 가능 할 때(output buffer 가 write 해도 충분할 정도로 비워졌을때) 호출된다. 이 함수들은 오버라이딩해서 "워터마크"를 읽기/쓰기 를 하도록 수정 가능하다.

모든 bufferevent 들은 4개의 "워터 마크"를 가진다.

  • Read low-water mark
여기에 설정된 레벨 이상의 데이터가 채워지면 해당 bufferevent 의 read 콜백 함수가 호출된다. 기본값은 0 이다. 따라서 어떤 경우에도 read 콜백이 호출된다.
  • Read high-water mark
If the bufferevent’s input buffer ever gets to this level, the bufferevent stops reading until enough data is drained from the input buffer to take us below it again. Defaults to unlimited, so that we never stop reading because of the size of the input buffer.
  • Write low-water mark
Whenever a write occurs that takes us to this level or below, we invoke the write callback. Defaults to 0, so that a write callback is not invoked unless the output buffer is emptied.
  • Write high-water mark
Not used by a bufferevent directly, this watermark can have special meaning when a bufferevent is used as the underlying transport of another bufferevent. See notes on filtering bufferevents below.

이뿐만이 아니라, bufferevent 는 non-data-oriented 이벤트를 위한 "에러" 혹은 "이벤트" 를 위한 콜백을 가지고 있다. 예를 들면 연결이 에러로 인해 종료가 되었을 때 사용된다. 다음의 Flag 들을 설정할 수 있다.

  • BEV_EVENT_READING
eventbuffer 에서 read 작업 중 발생하는 이벤트.
  • BEV_EVENT_WRITING
eventbuffer에서 write 작업 중 발생하는 이벤트.
  • BEV_EVENT_ERROR
eventbuffer 작업중 붕 발생하는 에러. 발생된 에러에 대한 더 자세한 정보를 확인하고 싶다면 EVUTIL_SOCKET_ERROR() 함수를 호출하면 된다.
  • BEV_EVENT_TIMEOUT
bufferevent 에서 timeout 발생
  • BEV_EVENT_EOF
bufferevent 에서 End-of-file 발생
  • BEV_EVENT_CONNECTED
bufferevent 에서의 연결 요청 완료 발생.

Deferred callbacks

기본적으로 bufferevent 콜백은 해당 조건이 충족되면, 그 즉시 호출된다.(이 부분은 evbuffer 역시 동일하다). 이런 즉각 호출은 해당 bufferevent의 의존성으로 인해 문제를 야기할 수 있다. 예를 들어 evbuffer A 로 데이터를 move 하는 콜백이 있다고 가정해보자. 그리고 evbuffer A가 비게되면 다른 콜백이 evbuffer A에 데이터를 입력하자고 해보자. 그렇게되면 모든 콜백들은 스택에 쌓이기 시작하여 마친되는 stack overflow 를 일으킬 것이다.

이를 해결하기 위해서 bufferevent(혹은 evbuffer)의 콜백이 뒤늦게 동작하도록 설정할 수 있다. 콜백이 즉시 호출 대신, 지연 호출되게 되면, 이벤트 루프에 쌓이게 되고, 후에 차례가 왔을 때, 보통의 이벤트 콜백 처럼 사용할 수 있다.

Option flags for bufferevents

bufferevent 생성시, 하나의 혹은 그 이상의 flag를 조합하여 동작 내용을 변경할 수 있다.

  • BEV_OPT_CLOSE_ON_FREE
bufferevent 가 freed 상태일 때,


References

<references />