👉🏻 void RtmpSession::read_chunk_header() {} 함수에 대한 설명입니다.
This is a description of the void RtmpSession::read_chunk_header() {} function.
✔️ 여기서는 소켓에서 1바이트(8비트)를 읽어와서 fmt와 cs_id를 추출합니다.
Here, we read 1 byte (8 bits) from the socket to extract fmt and cs_id.
| fmt 값/value | MessageHeader 크기 | 의미 / meaning |
| 0 | 11Byte | 풀 헤더/Full Header |
| 1 | 7Byte | stream_id 생략 / Stream_id omitted |
| 2 | 3Byte | only timestamp |
| 3 | 0Byte | 헤더 없음 no header |
✔️ 소켓에서1 바이트 읽기
Read 1 byte from socket
— 1바이트는 8비트입니다.(7,6,5,4,3,2,1,0)
1 byte is 8 bits. (7,6,5,4,3,2,1,0)
— 8비트의 값은 설명을 위해 0x43 = 01000011 = 67 이 값으로 합니다.
For the purpose of explanation, the 8-bit value is set to 0x43 = 01000011 = 67.
socket_.async_read_some(asio::buffer(&chunk_basic_header_, 1)
✔️ 변수 생략 / Variable omitted
— C++문법상 사용되지 않는 변수명 생략 가능해서 생략되었습니다.
Variable names not used in C++ syntax can be omitted, so they have been omitted.
# 변수 생략된 코드
# Code with omitted variables
[this, self](std::error_code ec, std::size_t) {...}
# 변수 생략 이전
# Before variable omission
[this, self](std::error_code ec, std::size_t bytes_transferred) { ... }
✔️ fmt값 추출,오른쪽으로 6비트 밀기
Extract fmt value, shift right by 6 bits
— fmt값은 0,1,2,3밖에 없기 때문에 0,1비트위치의 값만 사용합니다.
Since fmt values are only 0, 1, 2, and 3, only the values at bit positions 0 and 1 are used.
— 그래서 6비트 밀어서 7번비트가 1번비트에 오도록 비트를 내립니다.
So, we shift by 6 bits to lower the bit so that the 7th bit becomes the 1st bit.
— 비트 이동후에
After moving the beat
uint8_t fmt = (chunk_basic_header_ >> 6) & 0x03;
— 오른쪽으로 6비트 밀기란?(예:)
What is shifting 6 bits to the right? (e.g.)
비트번호/bit bumber:
[7 6][ 5 4 3 2 1 0]
[fmt][ cs_id ]
2-bit 6-bit
0x43 = 01000011 = 67
원본/original value:
0 1 0 0 0 0 1 1
>> 6 적용/apply
1. 오른쪽으로 1칸/1 spaces to the right: 00100001
2. 오른쪽으로 2칸/2 spaces to the right: 00010000
3. 오른쪽으로 3칸/3 spaces to the right: 00001000
4. 오른쪽으로 4칸/4 spaces to the right: 00000100
5. 오른쪽으로 5칸/5 spaces to the right: 00000010
6. 오른쪽으로 6칸/6 spaces to the right: 00000001
— & 0x03 이 6비트 0으로 덮어 씌우기
& Overwrite 0x03 with 6-bit 0
–AND연산은 둘다 1인 경우만 1이됨(&)
The AND operation returns 1 only when both are 1 (&)
01000001 ← >> 6 비트이동한 결과 / 6 Bit shift result
& 00000011 ← 0x03 마스크 / 0x03 mask
00000001 ← 하위 2비트만 살아남음 / Only the lower 2 bits survive
✔️ cs_id 추출 / Extract cs_id
— & 0x3F는 하위 6비트만 뽑아서 cs_id 만드는 입니다.
& 0x3F is used to create cs_id by extracting only the lower 6 bits.
— fmt가 7,6번 비트로 만들었고 나머지 0~5비트로 AND 연산하면 10진수로 3만 남습니다.
fmt is created using bits 7 and 6, and performing an AND operation with the remaining bits 0 through 5 leaves only 3 in decimal.
— 그래서 따로 비트이동은 하지 않습니다.
Therefore, we do not perform separate bit shifting.
–AND연산은 둘다 1인 경우만 1이 됩니다.(&)
The AND operation returns 1 only when both are 1. (&)
01000011 ← chunk_basic_header_ = 0x43 = 67
& 00111111 ← 0x3F 마스크 / 0x3F mask
00000011 ← 결과 / result = 3
✔️ 그래서 fmt = 1 = “헤더 7바이트”,cs_id = 3 = “3번 채널” 이 됩니다.
So, fmt = 1 = “7 bytes of header”, cs_id = 3 = “channel 3”.
✔️ cs_id는 26 = 64 (0~63)개의 채널을 사용할 수 있습니다.(cs_id = 0~63)
cs_id is 26 = 64 (0~63) channels can be used. (cs_id = 0~63)
✔️ 만약 cs_id == 0이면 1바이트를 더 읽어서 채널을 (64+255=)319개 더 확장합니다.
If cs_id == 0, read 1 more byte to expand the channel to (64+255=)319 more.
— 1byte = 8bit = 255까지 사용가능
1 byte = 8 bits = up to 255 can be used
if (cs_id == 0) {
uint8_t ext;
asio::async_read(socket_, asio::buffer(&ext, 1),
[this, self, fmt, ext](std::error_code ec, std::size_t) {
if (ec) return;
read_message_header(fmt, 64 + ext);
});
}
✔️ cs_id == 1이면 2바이트를 읽어서 buf[2]배열에 각각 저장합니다.
If cs_id == 1, read 2 bytes and store them in the buf[2] array.
✔️ 최대: 64 + 255 + (255<<8) = 64 + 255 + 65280 = 65599 개 까지의 채널을 사용할 수 있습니다.
Max: 64 + 255 + (255<<8) = 64 + 255 + 65280 = 65599 channels can be used.
else if (cs_id == 1) {
uint8_t buf[2];
asio::async_read(socket_, asio::buffer(buf, 2),
[this, self, fmt, buf](std::error_code ec, std::size_t) {
if (ec) return;
read_message_header(fmt, 64 + buf[0] + (buf[1] << 8));
});
}
✔️ 64 + buf[0] + (buf[1] << 8) 계산
— 소켓으로 0x10 0x01 2바이트 값이 날아오면
If a 2-byte value 0x10 0x01 is sent through the socket
— buf[0] = 0x10 = 00000001 = 1 ,buf[1] = 0x01 = 00010000 = 16
— 리틀엔디안인경우 상위 바이트를 왼쪽으로 8비트 밀어서 256(=100000000 )을 만듦
In the case of Little Endian, the upper byte is shifted left by 8 bits to create 256 (= 100000000).
— 예시 / example:
buf[1]=0x01: 0x01 << 8 = 0x0100 = 256 ,
buf[0]=0x10: 0x10 = 16
합계/total: 256 + 16 = 272
최종/final cs_id = 64 + 272 = 336
— 최소값/minimum value :
buf[0] = 0x00 = 0,
buf[1] = 0x00 = 0 ,
cs_id = 64 + 0 + (0 << 8) = 64 + 0 + 0 = 64
— 최대값/maximum value:
buf[0] = 0xFF = 255,
buf[1] = 0xFF = 255,
buf[1] << 8 = 0xFF << 8 = 0xFF00 = 65280,
cs_id = 64 + 255 + 65280 = 65599
✔️ 함수 전체 코드 / full function code
void RtmpSession::read_chunk_header() {
auto self(shared_from_this());
// 1바이트만 읽기 / Read only 1 byte
socket_.async_read_some(asio::buffer(&chunk_basic_header_, 1),
[this, self](std::error_code ec, std::size_t) {
if (ec) {
std::cout << "[Info] Connection closed: " << ec.message() << "\n";
return;
}
uint8_t fmt = (chunk_basic_header_ >> 6) & 0x03;
uint32_t cs_id = chunk_basic_header_ & 0x3F;
if (cs_id == 0) {
uint8_t ext;
asio::async_read(socket_, asio::buffer(&ext, 1),
[this, self, fmt, ext](std::error_code ec, std::size_t) {
if (ec) return;
read_message_header(fmt, 64 + ext);
});
} else if (cs_id == 1) {
uint8_t buf[2];
asio::async_read(socket_, asio::buffer(buf, 2),
[this, self, fmt, buf](std::error_code ec, std::size_t) {
if (ec) return;
read_message_header(fmt, 64 + buf[0] + (buf[1] << 8));
});
} else {
read_message_header(fmt, cs_id);
}
});
}