这是我的功能:
void connection(int sock) // sock is a descriptor of socket
{
char buffer[MAX];
int n; // number of bytes read or write into a socket
int f;
f = fork();
if(write(sock,"HELLO\n", 5) < 0)
{
perror("Error: \n");
}
write(sock, "\n> ",3);
do {
memset(buffer,'0',MAX); //
n = read(sock,buffer,MAX -1 );
if (strncmp("get",buffer,3) == 0)
{
if(f == 0)
{
write(sock, "TOP:\n",4);
dup2(sock,1);
if(execl("/usr/bin/top","/usr/bin/top","-bn1",0) == -1)
write(sock, "ERROR",5);
}
else
{
waitpid(f, NULL, 0);
write(sock, "\n> ",3);
}
}
else if (strncmp("quit",buffer,4) == 0)
{
write(sock, "EXIT\n",4);
close(sock);
exit(0);
}
else
{
write(sock,"Wrong order\n", 12);
write(sock, "> ",2);
}
}
while(n);
}
该函数负责客户端和服务器之间的信息交换。服务器应发送“top”操作的结果。
这个函数是TCP服务器程序的一部分。
当客户端通过 telnet 帮助连接到服务器时,他看到:
> Hello
> //(and here I can write "get", to see top results)
我想在调用“get”之后再次看到“>”,所以我输入了: 否则
{
waitpid(f, NULL, 0);
write(sock, "\n> ",3);
}
但是我没有看到我的“>”。我可以看到它,只有当我在 telnet 中写别的东西时。我应该在我的子进程中放入什么来调用我的父进程?
问候。
最佳答案
1) memset(buffer,'0',MAX);
将 ASCII 字符“0”写入缓冲区中的所有字节。因此,无法保证您读取的字符串以 null 结尾。
2) 您的“命令行”处理不能正确处理关闭的套接字。它退出 do...while
循环,从 connection()
返回……这可能不是您想要的。您可能希望它执行与“退出”命令相同的操作。 “退出”命令应该是 break;
而不是 exit(0);
,并且 exit(0);
应该放在while(n);
.
3) 在 fork()
之后,子进程和父进程将打开相同的文件。每个进程都应该关闭它不再使用的文件。至少,这意味着父项 (f != 0) 需要关闭 sock
,因为它现在是子项的属性。此外,服务器(实际上是监听器)进程应该在生成子进程后返回监听更多连接。为此,将其放在 f = fork()
行之后:
if(f != 0) // Or just 'if(f)' if your coding standards allow it.
{ // Parent continues here
close(sock);
return; // Or 'return f;' if you want to save the child's process ID for later.
}
// Child starts here
如果父进程打开了子进程不应弄乱的文件,则应在此 if(f != 0)
block 之后立即关闭它们。
4) 不能保证对 read()
的调用会让你得到一行,除非有东西在执行行缓冲(也许是你的终端?)。
5) 在执行 read()
之前,您应该在 do...while
循环中写出提示。
6) 当您execl()
时,您当前的进程消失了,并且无法返回。我建议您研究 popen()
命令集并改用它们。
关于c - 关于 fork() 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1992687/