套接字编程中的霍夫曼编码
Huffman encoding in socket programming
我想在用 C 编写的客户端服务器套接字程序中使用霍夫曼代码
所以我编写了一个代码,用于从文本文件作为输入生成霍夫曼树。
但是,我不知道如何在客户端服务器套接字程序中使用它。
到目前为止,我已经考虑了以下方法--
1)通过套接字连接以位的形式发送编码文件。不能这样做,因为我使用的是 C 语言并且没有位数据类型(我怀疑任何语言中是否存在位数据类型)。
2)以整数0和1的形式发送数据。那将完全破坏目的。 Char(1字节) Int(至少4字节)
你必须自己将这些位打包成字节。这并非特定于 C - 很少有语言具有位数据类型。
你需要"save up"8位,然后将它们转换成一个字节,然后发送这个字节。大概是这样:
int bitBuffer = 0;
int numberOfSavedBits = 0;
// bit must be 1 or 0
void sendBit(int bit) {
bitBuffer |= (bit << numberOfSavedBits);
numberOfSavedBits++;
if (numberOfSavedBits == 8) {
sendByte(bitBuffer);
numberOfSavedBits = 0;
bitBuffer = 0;
}
}
接收时还需要做相反的转换
只需将您的位打包成字节即可。通过使用按位运算符,这是一项非常简单的任务。例如
uint32_t value = 0;
value |= 1 << 3; // set fourth bit to one
bool isFourthBitSet = value & (1 << 4); // check if fifth bit is set
你也可以使用位包结构,比如
union compressed_byte {
struct {
uint8_t b0 : 1;
uint8_t b1 : 1;
..
}
uint8_t raw;
}
让所有这些操作对用户透明。当然你必须保证client和socket都使用相同的内存布局。此外,如果您打包到大于 1 字节的单元中,您还必须确保相同的字节顺序。
您需要获取 0
和 1
值并将它们打包到 char
数组的位中。
例如,假设您有以下包含 16 个 int
个值的数组:
[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15]
---------------------------------------------------------------------------------
| 0 | 1 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 |
---------------------------------------------------------------------------------
您可以使用以下二进制格式将其压缩为 2 char
个值:
[0] [1]
-----------------------
| 01011101 | 00100011 |
-----------------------
在发件人端,您可以像这样打包位:
int encodedValues[1024];
...
// set encodedValues
...
char packedValues[128] = {0};
int i;
for (i=0; i<1024; i++) {
if (encodedValues[i]) {
packedValues[i/8] |= (1 << (i % 8));
}
}
然后在另一边,你打开它们:
char packedValues[128];
...
// receive packedValues
...
int encodedValues[1024] = {0};
for (i=0; i<1024; i++) {
encodedValues[i] = ((packedValues[i/8] & (1 << (i % 8))) != 0);
}
我想在用 C 编写的客户端服务器套接字程序中使用霍夫曼代码
所以我编写了一个代码,用于从文本文件作为输入生成霍夫曼树。
但是,我不知道如何在客户端服务器套接字程序中使用它。
到目前为止,我已经考虑了以下方法--
1)通过套接字连接以位的形式发送编码文件。不能这样做,因为我使用的是 C 语言并且没有位数据类型(我怀疑任何语言中是否存在位数据类型)。
2)以整数0和1的形式发送数据。那将完全破坏目的。 Char(1字节) Int(至少4字节)
你必须自己将这些位打包成字节。这并非特定于 C - 很少有语言具有位数据类型。
你需要"save up"8位,然后将它们转换成一个字节,然后发送这个字节。大概是这样:
int bitBuffer = 0;
int numberOfSavedBits = 0;
// bit must be 1 or 0
void sendBit(int bit) {
bitBuffer |= (bit << numberOfSavedBits);
numberOfSavedBits++;
if (numberOfSavedBits == 8) {
sendByte(bitBuffer);
numberOfSavedBits = 0;
bitBuffer = 0;
}
}
接收时还需要做相反的转换
只需将您的位打包成字节即可。通过使用按位运算符,这是一项非常简单的任务。例如
uint32_t value = 0;
value |= 1 << 3; // set fourth bit to one
bool isFourthBitSet = value & (1 << 4); // check if fifth bit is set
你也可以使用位包结构,比如
union compressed_byte {
struct {
uint8_t b0 : 1;
uint8_t b1 : 1;
..
}
uint8_t raw;
}
让所有这些操作对用户透明。当然你必须保证client和socket都使用相同的内存布局。此外,如果您打包到大于 1 字节的单元中,您还必须确保相同的字节顺序。
您需要获取 0
和 1
值并将它们打包到 char
数组的位中。
例如,假设您有以下包含 16 个 int
个值的数组:
[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15]
---------------------------------------------------------------------------------
| 0 | 1 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 |
---------------------------------------------------------------------------------
您可以使用以下二进制格式将其压缩为 2 char
个值:
[0] [1]
-----------------------
| 01011101 | 00100011 |
-----------------------
在发件人端,您可以像这样打包位:
int encodedValues[1024];
...
// set encodedValues
...
char packedValues[128] = {0};
int i;
for (i=0; i<1024; i++) {
if (encodedValues[i]) {
packedValues[i/8] |= (1 << (i % 8));
}
}
然后在另一边,你打开它们:
char packedValues[128];
...
// receive packedValues
...
int encodedValues[1024] = {0};
for (i=0; i<1024; i++) {
encodedValues[i] = ((packedValues[i/8] & (1 << (i % 8))) != 0);
}