还是先看写string的方法:
writeStringBinary((DBMS_NAME " ") + client_name, *out);//将"ClickHouse client"写到out中
即把字符串‘ClickHouse client’写到out中。
inline void writeStringBinary(const std::string & s, WriteBuffer & buf)
{
//向Buffer中写入字符串
//1-先写入该字符串的长度s.size()
writeVarUInt(s.size(), buf);
//2-再将字符串写入
buf.write(s.data(), s.size());
}
即先写字符串的长度,再写具体的字符信息。writeVarUInt()方法之前已经分析过了,看下write()方法,
/// 同ReadBuffer的read方法,
/// 从from中拷贝n个字节写到buffer中
void write(const char * from, size_t n)
{
size_t bytes_copied = 0;
while (bytes_copied < n) //判断是否已经拷贝了n个字节
{
nextIfAtEnd();
size_t bytes_to_copy = std::min(static_cast<size_t>(working_buffer.end() - pos), n - bytes_copied);
memcpy(pos, from + bytes_copied, bytes_to_copy);
pos += bytes_to_copy;
bytes_copied += bytes_to_copy;
}
}
服务端是怎么读的呢?源码如下:
readStringBinary(client_name, *in);
即把字符串‘ClickHouse client’从in中读取出来,保存到client_name中。
inline void readStringBinary(std::string & s, ReadBuffer & buf, size_t MAX_STRING_SIZE = DEFAULT_MAX_STRING_SIZE)
{
size_t size = 0;
readVarUInt(size, buf);
if (size > MAX_STRING_SIZE)
throw Poco::Exception("Too large string size.");
s.resize(size);
buf.readStrict(s.data(), size);
}
也是先读取字符串的长度,再读取具体的字符信息。
/** Reads n bytes, if there are less - throws an exception. */
//读取n个字节. 字节数小于n时抛出异常
void readStrict(char *to, size_t n) {
//read(to, n)方法从buffer中读取n个字节, 保存到to中
auto read_bytes = read(to, n);
if (n != read_bytes)
throw Exception(
"Cannot read all data. Bytes read: " + std::to_string(read_bytes) + ". Bytes expected: " +
std::to_string(n) + ".", ErrorCodes::CANNOT_READ_ALL_DATA);
}
/** Reads as many as there are, no more than n bytes. */
size_t read(char *to, size_t n) {
size_t bytes_copied = 0;
while (bytes_copied < n && !eof()) {
size_t bytes_to_copy = std::min(static_cast<size_t>(working_buffer.end() - pos), n - bytes_copied);
::memcpy(to + bytes_copied, pos, bytes_to_copy);//内存拷贝函数memcpy(dest, src, size)
pos += bytes_to_copy;
bytes_copied += bytes_to_copy;
}
return bytes_copied;
}