我正在通过套接字编程并很好地实现它..现在我想在ls
其中实现一个系统调用..
当输入ls
在客户端机器上给出时,服务器的输出应该打印在客户端机器上(即命令应该在服务器端执行,输出应该重定向到客户端......)
我如何收集服务器机器的输出?
我只需要提示..谢谢
您可以使用dup2将stdout
(或任何其他现有 fd)重定向到您的套接字 fd。例子:
int client_fd = accept(server_fd, 0, 0);
assert(client_fd != -1);
close(0); // Close stdout
dup2(client_fd, 0); // Redirect stdout to client_fd
这应该可以解决问题:-)
编辑 1下面的示例显示了一个连接到 127.0.0.1:1234 的客户端程序,生成一个 shell 进程,并重定向 IO,以便 shell 自动为您处理所有通信。您可以通过在另一个终端中运行netcat -l 1234来测试它,然后运行该程序并发送ls
来自 netcat 的命令。将其调整为在服务器端工作留作练习。
重要提示:此程序提供对机器外壳的未经身份验证的访问。
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
int exec_shell(int sock_fd) {
// Redirect IO
dup2(sock_fd, 0);
dup2(sock_fd, 1);
dup2(sock_fd, 2);
// Execute shell
execl("/bin/sh", "sh", NULL);
return 0;
}
int main() {
int fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in sa_dst;
memset(&sa_dst, 0, sizeof(struct sockaddr_in));
sa_dst.sin_family = AF_INET;
sa_dst.sin_port = htons(1234);
sa_dst.sin_addr.s_addr = inet_addr("127.0.0.1");
int ret = connect(fd, (struct sockaddr *)&sa_dst, sizeof(struct sockaddr));
assert(ret != -1);
exec_shell(fd);
close(fd);
return EXIT_SUCCESS;
}
create the empty file like cat > file and ctrl+d the filename is file
client:
Get the Input from the user
ls
n=send(sockfd, msg, 1000,0); //msg contains the ls
send function using send the message to the server
Server:
Receive function using receive the client message
n=receive(sockfd, msg, 1000,0);
FILE *fp;
recvbuf[strlen(recvbuf)-1]=0; // client msg received and delete the \n
strcat(recvbuf,">file"); // add to redirected file
printf("Recvbuf:%s\n",recvbuf); // ls>file
int status=0;
pid_t pid=vfork();
if(pid==0)
execlp("sh","sh","-c",recvbuf,(char *)0); // executed the ls command and redirected to file
else
{
wait(&status);
fp=fopen("file","r"); //open the file read the content and stored to buffer
while((c=getc(fp))!=EOF)
buf1[i++]=c;
buf1[i]='\0';
printf("%s\n",buf1);
fclose(fp);
}
Again server send the buffer to the clientfd so the output redirected to client.
send(sockfd,buf1,1000,0);
Finally client receive the output of command
如果我正确理解了这个问题,我的“提示”将是使用以下内容:
popen()
执行ls命令。fileno()
.sendfile()
将其复制到 client_fd。Edit: sendfile()
is non-standard and might not be portable. You can replace it with a read-write loop (reading the FILE * writing into client_fd), if you want, but its more work.