请考虑以下代码:
writer.c
mkfifo("/tmp/myfifo", 0660);
int fd = open("/tmp/myfifo", O_WRONLY);
char *foo, *bar;
...
write(fd, foo, strlen(foo)*sizeof(char));
write(fd, bar, strlen(bar)*sizeof(char));
Run Code Online (Sandbox Code Playgroud)
reader.c
int fd = open("/tmp/myfifo", O_RDONLY);
char buf[100];
read(fd, buf, ??);
Run Code Online (Sandbox Code Playgroud)
我的问题是:
既然事先不知道foo和bar有多少字节,我怎么知道从reader.c读取多少字节?
因为,例如,如果我在阅读器中读取10个字节,并且foo和bar一起小于10个字节,我将把它们放在同一个变量中并且我不想要它们.
理想情况下,我会为每个变量都有一个读取函数,但我再次不知道数据有多少字节.
我想在write.c中使用分隔符在write for foo和bar之间添加另一个写指令,然后我就没有问题从reader.c解码它.这是怎么回事?
谢谢.
许多其他答案提到为您的数据使用某种协议,我相信这是正确的方法.该协议可以根据需要简单或复杂.我提供了一些你可能会觉得有用的例子1.
在一个简单的例子中,您可能只有一个长度字节后跟数据字节(即C字符串).
+--------------+ | length byte | +--------------+ | data byte(s) | +--------------+
作家:
uint8_t foo[UCHAR_MAX+1];
uint8_t len;
int fd;
mkfifo("/tmp/myfifo", 0660);
fd = open("/tmp/myfifo", O_WRONLY);
memset(foo, UCHAR_MAX+1, 0);
len = (uint8_t)snprintf((char *)foo, UCHAR_MAX, "Hello World!");
/* The length byte is written first followed by the data. */
write(fd, len, 1);
write(fd, foo, strlen(foo));
Run Code Online (Sandbox Code Playgroud)
读者:
uint8_t buf[UCHAR_MAX+1];
uint8_t len;
int fd;
fd = open("/tmp/myfifo", O_RDONLY);
memset(buf, UCHAR_MAX+1, 0);
/* The length byte is read first followed by a read
* for the specified number of data bytes.
*/
read(fd, len, 1);
read(fd, buf, len);
Run Code Online (Sandbox Code Playgroud)
在更复杂的情况下,您可能有一个长度字节,后跟包含多个简单C字符串的数据字节.
+----------------+ | length byte | +----------------+ | data type byte | +----------------+ | data byte(s) | +----------------+
普通标题:
#define FOO_TYPE 100
#define BAR_TYPE 200
typedef struct {
uint8_t type;
uint32_t flags;
int8_t msg[20];
} __attribute__((aligned, packed)) foo_t;
typedef struct {
uint8_t type;
uint16_t flags;
int32_t value;
} __attribute__((aligned, packed)) bar_t;
Run Code Online (Sandbox Code Playgroud)
作家:
foo_t foo;
unsigned char len;
int fd;
mkfifo("/tmp/myfifo", 0660);
fd = open("/tmp/myfifo", O_WRONLY);
memset(&foo, sizeof(foo), 0);
foo.type = FOO_TYPE;
foo.flags = 0xDEADBEEF;
snprintf(foo.msg, 20-1, "Hello World!");
/* The length byte is written first followed by the data. */
len = sizeof(foo);
write(fd, len, 1);
write(fd, foo, sizeof(foo));
Run Code Online (Sandbox Code Playgroud)
读者:
uint8_t buf[UCHAR_MAX+1];
uint8_t len;
uint16_t type;
union data {
foo_t * foo;
bar_t * bar;
}
int fd;
fd = open("/tmp/myfifo", O_RDONLY);
memset(buf, UCHAR_MAX+1, 0);
/* The length byte is read first followed by a read
* for the specified number of data bytes.
*/
read(fd, len, 1);
read(fd, buf, len);
/* Retrieve the message type from the beginning of the buffer. */
memcpy(&type, buf, sizeof(type));
/* Process the data depending on the type. */
switch(type) {
case FOO_TYPE:
data.foo = (foo_t)buf;
printf("0x%08X: %s\n", data.foo.flags, data.foo.msg);
break;
case BAR_TYPE:
data.bar = (bar_t)buf;
printf("0x%04X: %d\n", data.bar.flags, data.bar.value);
break;
default:
printf("unrecognized type\n");
}
Run Code Online (Sandbox Code Playgroud)
1 - 此代码是从内存中编写的,未经测试.
分隔符是一种方法,只要您知道数据的顺序,并且只使用分隔符作为分隔符,而不是作为数据的一部分,这将正常工作.
另一种方法是在每个写入管道之前,使用固定宽度的字节数.因此,您将知道有多少数据即将进入管道.使用固定宽度,因此您可以准确知道宽度字段的长度,因此您知道何时开始和停止读取每个数据块.
| 归档时间: |
|
| 查看次数: |
2702 次 |
| 最近记录: |