我正在尝试编写一个程序,该程序连接到在另一终端上用nc -v -l 1337
打开的服务器,并将stdin,stdout,stderr重定向到套接字。
意思是,另一个终端将写入套接字,并且我的程序将使用getchar()
读取套接字并使用printf()
进行响应。
我遇到了一些奇怪的事情-如果我注释掉首次使用printf(在dup2(sockfd,1)
之前)的话,一切都会正常进行。如果不是,则打印不执行任何操作。是什么原因造成的?
int main()
{
int sockfd, connfd;
struct sockaddr_in servaddr, cli;
// socket create and varification
sockfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr.sin_port = htons(1337);
connect(sockfd, (SA*)&servaddr, sizeof(servaddr));
dup2(sockfd,0);
//---------------------------
// printf("%s\n","hi" );
//---------------------------
dup2(sockfd,1);
dup2(sockfd,2);
char buff[80];
int n;
while(1){
n = 0;
while ((buff[n++] = getchar()) != '\n');
buff[n-1] = 0;
printf("message %s excepted\n",buff );
}
// close the socket
close(sockfd);
}
答案 0 :(得分:0)
修复:
您需要在写入程序时告诉程序刷新stdout
:
while(1){
n = 0;
while ((buff[n++] = getchar()) != '\n');
buff[n-1] = 0;
printf("message %s excepted\n",buff );
/* ask the system to flush stdout */
fflush(stdout);
}
原因:(我只是在猜测)
不是所有的FILE流都被相同的缓冲。
要打印\n
时,将刷新连接到终端的FILE流。
当缓冲区已满时,连接到套接字的文件流将被刷新。
通过在printf("...\n");
之前调用dup2();
,可以强制执行第一个行为。
答案 1 :(得分:0)
您的程序执行了预期的操作,dup2(sockfd,0);
将关闭客户端程序的标准输入(即,您在启动程序的终端中从键盘输入的文本),并使用{{1 }}作为新的标准输入。引自here:
dup2()使newfd成为oldfd的副本,必要时先关闭newfd
要证明这一点,请尝试以这种方式启动您的监听套接字程序:
sockfd
在1号航站楼cat | nc -v -l 1337
(例如strace
)包装套接字客户端程序在终端1(您启动服务器侦听端口1337的地方)中键入的文本将通过套接字发送,并通过strace a.out
在终端2中接收(现在是fd 0
的副本) ,并且由于将标准输出(fd 1)重定向到sockfd
而通过套接字发送回了。
如果您不想将文本发送回服务器,而是将其显示在终端2上,则可能要注释掉sockfd
。另外,您可能希望注释掉dup2(sockfd,1);
,以将客户端程序的标准输入保留在键盘上,并通过套接字将从端子2输入的文本发送出去。
不确定是否能回答您的问题,但是我认为dup2(sockfd,0);
+ strace
将帮助您了解如何管理适当的各种文件描述符。
希望这会有所帮助!
答案 2 :(得分:0)
我会说这可能是一个缓冲问题。一个常见的解决方法是,建议刷新套接字,否则尝试将stdout的缓冲区设置为0可能会解决此问题。
setbuf(stdout, NULL);