-
boost::asio::streambuf 분석..프로그래밍/c++ - boost::asio 2015. 9. 15. 15:13반응형
이전에는 수신 버퍼를 직접 만들어서 쓰고 있었다. 수신 버퍼의 이름은 StreamBuffer -_-
boost::asio::streambuf를 수신 버퍼로 쓰는 코드들을 c++ 오픈소스 그룹 커뮤니티에서 보았다.
streambuf는 뭐지? 뭔가 편해 보이는데..
이름도 streambuf인걸 보면 소켓 송수신에 쓰일 버퍼로 쓰라고 만들어놓은 거 같길래 여기저기서 코드 사용 예를 살펴보다가
이전에 내가 직접 만들었던 StreamBuffer와 뭔가 비슷하다고 느껴서 코드 내부를 직접 보게 됨
** 정의
std::streambuf를 상속 받는다.
복사가 불가능 함(boost::noncopyable 상속)
커스텀 할당자를 지원함
** 생성
최대 크기(maximum_size) 인자를 지정해주지 않으면 std::numeric_limits<std::size_t>::max() 값이 지정 됨
Allocator는 기본 할당자(std::allocator<char>)로 지정
** 멤버 변수 부분..
private:
std::size_t max_size_;
std::vector<char_type, Allocator> buffer_;
멤버로 std::vector와 최대 사이즈를 제한을 위한 max_size를 가지고 있다.
여기까지 파악할 수 있을 것들
- Streambuf의 크기는 가변적. 런타임에 크기를 지정하는 것도 가능하다.
- 최대 크기를 명시적으로 제한할 수 있음
- 커스텀 할당자를 사용할 수 있다.
** 멤버 함수들..
prepare(size_t n)
버퍼를 준비하는(prepare) 함수. Receive를 할 때 이 함수를 호출해서 쓰기 버퍼 영역을 만들면 된다. 처음에 봤을 땐 Prepare 자체에서 할당을 하나 했지만 기존에 있는 버퍼를 사용하는거였음. 윈속 프로그래밍을 하다보면 WSABUF라는 구조체를 사용하는데 그것과 같은 기능을 한다고 보면 될 것이다.
reserve(size_t n)
쓰기 공간을 예약하는 함수로 내부적으로 버퍼 트리밍하는 기능도 가지고 있다.
[버퍼의시작] … [읽기시작부분]…..[쓰기시작부분]…[버퍼끝] 이렇게 있을 때 쓰기 공간이 부족하면 읽기시작부분~쓰기시작부분을 앞으로 당겨서 공간을 확보하는 기능을 함.
consume(size_t n)
버퍼에서 데이터를 읽었을 때 읽기 인덱스를 뒤로 당기는 함수. 인자로 전달되는 n만큼 당긴다.
commit(size_t n)
버퍼에 데이터를 썼을 때 쓰기 인덱스를 뒤로 당기는 함수. 마찬가지로 n만큼 당김
data()
읽기 부분을 반환한다. 나는 버퍼의 시작점을 주는건줄 알았는데 -_-;;
size()
버퍼에 담겨진 데이터의 양을 반환함.
// 공간을 예약(reserve)하는 함수
// 버퍼에 데이터를 삽입하기 전, 공간은 충분히 확보가 되어있어야 한다.
// 따라서 데이터를 삽입을 준비할 때 이 함수가 호출된다.
// std::length_error 예외를 던진다.
// 버퍼의 공간을 준비하는 prepare 함수도 내부적으로 reserve를 호출 후 공간을 반환!
// 트림(trim)의 기능도 있다!
void reserve(std::size_t n) { // Get current stream positions as offsets. 얻는다 현 스트림 위치의 오프셋을 std::size_t gnext = gptr() - &buffer_[0]; std::size_t pnext = pptr() - &buffer_[0]; std::size_t pend = epptr() - &buffer_[0]; // Check if there is already enough space in the put area. 검사함 이미 충분히 공간이 확보되었는지 if (n <= pend - pnext) { return; } // Shift existing contents of get area to start of buffer. 기존에 있던 데이터들을 버퍼의 시작 지점(&buffer[0)]으로 이동시킴 if (gnext > 0) { pnext -= gnext; std::memmove(&buffer_[0], &buffer_[0] + gnext, pnext); } // Ensure buffer is large enough to hold at least the specified size. 확인한다 버퍼가 적어도 명시된 크기(n)를 수용할 수 있는지 if (n > pend - pnext) { if (n <= max_size_ && pnext <= max_size_ - n) { pend = pnext + n; buffer_.resize((std::max<std::size_t>)(pend, 1)); } else { std::length_error ex("boost::asio::streambuf too long"); boost::asio::detail::throw_exception(ex); } } // Update stream positions. // 스트림 위치를 갱신함 setg(&buffer_[0], &buffer_[0], &buffer_[0] + pnext); setp(&buffer_[0] + pnext, &buffer_[0] + pend); } // 데이터 receive 전, 공간을 준비하는 함수이다. // 인자로 전해지는 n의 크기만큼 공간을 준비한다. // 내부적으로 reserve 함수를 호출. mutable_buffers_type prepare(std::size_t n) { reserve(n); return boost::asio::buffer(boost::asio::mutable_buffer( pptr(), n * sizeof(char_type))); }
내가 만든 StreamBuffer를 이거로 대체해도 될 듯 기능이 거의 비슷하다.
++ 2016/04/11
이건 std::streambuf에 있는 함수인데 반환하는 것들은 다음과 같다.
// pbase write buffer의 처음
// epptr write buffer의 끝
// pptr write buffer의 현재 위치
// eback read buffer의 처음
// egptr read buffer의 끝
// gptr read buffer의 현재 위치
쓰기 버퍼의 총 량을 반환하는 함수는 다음과 같이 쓸 수 있다.
123456size_t capacity() const{return epptr() - pbase(); // 쓰기 버퍼의 끝 - 쓰기 버퍼의 처음}cs 반응형'프로그래밍 > c++ - boost::asio' 카테고리의 다른 글
asio::strand의 올바른 사용법 (0) 2015.12.02 boost::asio의 송신 함수. async_write, async_write_some, async_send의 차이 (0) 2015.11.10 boost::asio::streambuf에 custom memory allocator 붙이기 (0) 2015.11.07 boost::asio deadline_timer를 이용한 유니티의 Invoke함수 흉내 내기 (0) 2015.09.28 boost::asio 완료 핸들러에 제네릭 람다 사용 시 있었던 문제 (0) 2015.09.17