我正在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/