我正在尝试通过编写一个套接字监听器程序和一个应用程序通过套接字将其控制台重定向到监听器来模拟 telnet 功能。
在服务器端,我在我的本地 ip 上打开了一个套接字,一个定义的端口,并开始像这样监听它
sockfd = socket(AF_INET,SOCK_STREAM,0);
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
bind(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr);
listen(sockfd,5);
neewsockfd = accept(sockfd,(struct sockaddr*)&cli_addr,&clien);
然后我开始在一个单独的线程中读取传入的数据,如下所示:
while(1)
{
bzero(buffer,256);
n= read(newsockfd,buffer,255);
if(n>0)
printf("%s",buffer);
}
在监听代码之后的主例程中,我像这样添加了套接字数据发送部分。
while(1)
{
bzero(buffer,256);
getline(&buffer,&t,stdin);
n=send(newsockfd,buffer,strlen(buffer),MSG_EOR);
}
对于客户端,我是这样连接到服务器的。
sockfd = socket(AF_INET,SOCK_STREAM,0);
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
inet_pton(AfF_INET,hostip,&serv_addr.sin_addr.s_addr)
serv_addr.sin_port = htons(portno);
connect(sockfd,serv_addr,sizeof(serv_addr));
然后我将 stdin、stdout 和 stderr 复制到 sockfd 描述符以重定向控制台,如下所示。
dup2(sockfd,STDIN_FILENO);
dup2(sockfd,STDOUT_FILENO);
dup2(sockfd,STDERR_FILENO);
close(sockfd);
最后我在客户端有类似的东西来测试控制台重定向
while(1)
{
bzero(mystring,256);
i = getline(&string,&t,stdin);
printf("Input:%s-%d\n",mystring,i);
}
在上面的代码中,我希望 getline 被阻塞,直到我在服务器应用程序控制台上输入一些字符,但令我痛苦的是,它反复出现值 0。
知道为什么会出现这种行为吗?
最佳答案
混合套接字 stdio(3)
是个坏主意TM。 stdin
和 stdout
都是行缓冲,参见setbuf(3)
,这可能就是让您来到这里的原因。还有一个线程安全问题 - stdio
流被锁定,但由于您已经使用 GNU 扩展,您可以尝试他们的 unlocked同行。
编辑0:
根据您在评论中的输入,我认为这将是解决方案:
- 创建一个
pipe(2)
在执行fork(2)
之前在父进程中
- 在chaild进程中
dup2(2)
在fork(2)
之后但在execve(2)
之前,管道将文件描述符读入 - 在新的
exec
子进程中只读取标准输入 - 在父进程中复制标准输入到管道的写文件描述符中。
STDIN
这应该可以避免大部分混淆。
关于c - getline() 函数行为异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6923074/