简体   繁体   中英

read print out nothing after using fscanf

I'm writing a simple text-based protocol interpreter for server. The server will receive a response in the format of METHOD [filename]\\n[file_size][data] from socket, where the string length of METHOD , filename , and data vary. file_size is the number of bytes of data . Since the length of METHOD and filename vary, I try to use fscanf() to capture them. After that, I use read() to get file_size and data . However, the problem is read() never prints. I wrote a small case to illustrate my problem:

#define MSGSIZE 16 
char* msg1 = "hello world\n#1"; 
  
int main() 
{ 
    char inbuf[MSGSIZE], *buf_1, *buf_2; 
    int p[2], i; 
  
    if (pipe(p) < 0) 
        exit(1); 
  
    write(p[1], msg1, MSGSIZE); 
  
    FILE *fd = fdopen(p[0], "r");
    fscanf(fd, "%ms %ms\n", &buf_1, &buf_2);
    printf("buf_1: %s, buf_2: %s\n", buf_1, buf_2);

    // read never prints
    read(fileno(fd), inbuf, 3);
    printf("buf: %s\n", inbuf); 
    return 0; 
} 

I would expect fscanf() to move the character pointer to '#' in "hello world\\n#1", then read should be able to print out following characters, which didn't happen. I'm a bit confused because if I call fscanf() instead of read, it would print. Is this because fscanf() manipulates file indicator differently from read() ?

You should not mix operations on the FILE * with operations on the underlying file descriptor. If you just replace read with an fread , it should behave as you expect. The fscanf (probably, almost certainly) reads everything from the pipe and stores it in an internal buffer, so your read has no data left to consume. To access the internal buffer, use fread or fgetc or fgets , but don't try to work on the underlying file descriptor.

Mixing FILE* stream I/O with system calls on the underlying file descriptor is the problem. Here is a change I made that shows one way to avoid it in your code.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define MSGSIZE 16 
char* msg1 = "hello world\n#1\n"; 
  
int main() 
{ 
    char inbuf[MSGSIZE], *buf_1, *buf_2; 
    int p[2], i;

    if (pipe(p) < 0) 
        exit(1); 
  
    write(p[1], msg1, MSGSIZE); 
  
    FILE *fd = fdopen(p[0], "r");
    fscanf(fd, "%ms %ms\n", &buf_1, &buf_2);
    printf("buf_1: %s, buf_2: %s\n", buf_1, buf_2);

    // read never prints
    //retVal = read(fileno(fd), inbuf, 3);
    // replace read() with fgets()
    if(fgets(inbuf, sizeof(inbuf), fd) == NULL)
    {
        printf("Error with fgets()\n");
    }
    else
    {
        printf("buf: %s\n", inbuf); 
    }
    
    return 0; 
} 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM