c - 从线程中的 stdin 读取以写入 c 中的文件

标签 c multithreading

我正在c中使用TCP创建一个FTP服务器。我的文件传输遇到问题,我希望能够从客户端向服务器“放置”或从服务器“获取”文件。 我正在使用 select() 处理多重连接并使用线程来处理文件传输。 我创建了一个简单的 .c 示例来总结我的问题:

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

void    *read_stdin(void * null)
{
  int   fd;
  int   len;
  char  ret;
  char  buff[1024];

  fd = open("dest", O_RDWR | O_TRUNC | O_CREAT, 0600);
  len = 1;
  while (len)
   {
     ret = read(0, &len, 1);
     len = atoi(ret);
     if (len)
      {
       read(0, buff, len);
       write(fd, buff, len);
      }
   }
 return (null);
}

int             main()
{
 pthread_t     t;
 int           fd;
 char           len;
 char          buff[1024];

  pthread_create(&t, NULL, &read_stdin, NULL);
  fd = open("source", O_RDONLY);
  while ((len = read(fd, buff, 1024)))
    {
         write(0, &len, 1);
         write(0, buff, len);
    }
   write(0, "0", 1);
  pthread_join(t, NULL);
  return (0);
}

现在我的问题是线程中的 read() 被阻塞,它没有从主进程读取我在 STDIN 上写的内容,我不明白为什么,它在我的程序中做同样的事情吗但我不是从标准输入读取,而是从套接字读取,但为了简单起见,我在本例中使用了 stdin。

谢谢!

编辑:将主文件中的 len 从 int 更改为 char,并使用 char 读取 thread_func,然后使用 atoi() 进行转换。

最佳答案

write(0, &len, 1);len 的一个字节写入 stdin,但 len实际上有 sizeof(int) 字节。此外,当您使用 read(0, &len, 1); 读回该值时,您只读取一个字节,而不是 sizeof(int)

此外,每次执行循环时都会读入 len 并在流中接收一个随机值。除非您不小心将空字节读入len,否则条件将始终为真,并且您最终会陷入无限循环。读取整个流后,下一次读取调用将被阻塞。

所以你应该正确地将消息的长度写入套接字并正确地读回。此外,您还必须检查是否已读取所有字节,以防止读取调用被阻塞。

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

void* read_stdin(void * null) {
        int fd;
        char len;
        char ret;
        char buff[255];

        fd = open("dest", O_RDWR | O_TRUNC | O_CREAT, 0600);
        len = 1;
        while (len) {
                len = read(0, &len, sizeof(len));
                if (len) {
                        read(0, buff, len);
                        write(fd, buff, len);
                }
        }
        close(fd);
        return NULL;
}

int main() {
        pthread_t t;
        int fd;
        char len;
        char buff[128];

        pthread_create(&t, NULL, &read_stdin, NULL);
        fd = open("source", O_RDONLY);
        while (len = read(fd, buff, 128)) { // you can only read 128 characters as len is a signed char (assuming an eight bit byte)
                write(0, &len, sizeof(len));
                write(0, buff, len);
        }
        //write(0, "0", 1);
        close(0);
        close(fd);
        pthread_join(t, NULL);

        return 0;
}

请注意,此代码仅在 stdin 未绑定(bind)到 tty 时才有效。如果是,终端会先读取它,然后您才能自己读取。 如果 stdin 绑定(bind)到 tty,您将需要一个管道或套接字对,正如 loreb 在他的回答中提到的那样。

我尝试尽可能少地调整您的代码,只是为了使其正常工作。它仍然不太好而且容易出错。不幸的是,我没有任何引用资料来说明如何正确地做这件事。但也许这里的其他人可以提供引用。

关于c - 从线程中的 stdin 读取以写入 c 中的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24907818/

相关文章:

c - 用于附加字符串的 sprintf vs strcat

c++ - 我可以将 boost::threadpool 用作 'thread-safe queue' 吗?

multithreading - 我在哪里可以找到多线程/并发 Playground ?

java - Java hashMap 中的线程安全

c - 如何从 C 代码生成#define 值列表?

C:绘制大型图书馆

python - 包装几个 C 源(.c 文件)以使用 SWIG 在 Python 中使用它们的函数

c - C中的静态分配邻接矩阵图

java - 处理日志文件,在工作线程之间分配工作,找到一个简单的总和

Python : how to stop a thread that's waiting for a . recv()