这是我的功能:
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);
}
此功能负责客户端和服务器之间的信息交换。服务器应该发送“顶部”操作的结果。
此功能是TCP服务器程序的一部分。
当客户端使用telnet帮助与服务器连接时,他会看到:
> Hello
> //(and here I can write "get", to see top results)
我想看看“&gt;”再次,在致电“得到”之后,我放了: 其他
{
waitpid(f, NULL, 0);
write(sock, "\n> ",3);
}
但我没有看到我的“&gt;”。只有当我用telnet写别的东西时,我才能看到它。我应该在fork的子进程中放入什么来调用我的父进程?
问候。
答案 0 :(得分:4)
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)
阻止后立即关闭。
4)无法保证拨打read()
会让你获得一条线路,除非某些线路正在执行线路缓冲(可能是你的终端?)。
5)您应该在read()
循环内do...while
之前写出提示。
6)当你execl()
时,你当前的过程消失了,没有办法回来。我建议您调查popen()
命令集并改为使用它们。
答案 1 :(得分:3)
父母和孩子都将HELLO发送到套接字。并且都从套接字读取。这是一种奇怪的行为。
如果你想要的是打开一个单独的进程来管理连接,你应该像现在一样在开头分叉,并立即用'if(f == 0)'分隔父进程和子进程。如果我正确理解你的意图,那么孩子应该发送HELLO等。