如何将执行命令的结果从服务器发送到客户端?

我正在用C实现一个套接字程序。

节目介绍:
连接服务器和客户端后,客户端向服务器发送命令。
服务器从客户端接收请求并执行它。
服务器将执行结果发送给客户端。
客户端将显示该服务器的执行和显示。

我的问题:
服务器:
我将execvp()函数的结果放入pipe pipefd[1]并使用send()将此数据发送到客户端。
客户:
我收到recv()数据到服务器和显示。

但它不起作用。

我想要的结果:
客户ls

服务器:

a.txt b.pdf c.jpg

客户:

a.txt b.pdf c.jpg

这是我的代码:

服务器:

 #include  #include  #include  #include  #include  #include  #include  #include  #define MAXPENDING 5 #define BUFFSIZE 32 #define MAX 128 void Die(char *mess) { perror(mess); exit(1); } void setup(char inputBuffer[], char *args[], int *background) //Ham xu li (cat) chuoi lenh { const char s[4] = " \t\n"; char *token; token = strtok(inputBuffer, s); int i = 0; while( token != NULL) { args[i] = token; i++; //printf("%s\n", token); token = strtok(NULL,s); } args[i] = NULL; } void HandeClient(int sock){ char buffer[BUFFSIZE]; int received = -1; char data[MAX]; data[0] = '\0'; /*recv() from client;*/ if((received = recv(sock, buffer,BUFFSIZE,0))0) { /* send() from server; //acknowledge to client */ if(send(sock,buffer, received,0)!= received){ Die("Failed"); } /* recv() from client; */ if((received=recv(sock,buffer,BUFFSIZE,0))0) { // parent process // write to pipe execvp(args[0],args); dup2(1,pipefd[1]); close(pipefd[0]); write(STDOUT_FILENO,pipefd[1],strlen(pipefd[1])); close(pipefd[1]); while (wait(NULL) != pid); } else if(pid==0) { //child process // read from pipe close(pipefd[1]); while(lenght=read(pipefd[0],path,1) > 0){ // send the result of execvp for client. if(send(sock,path,strlen(path),0) != strlen(path) ){ Die("Failed"); } } close(pipefd[0]); exit(1);// } else { printf("Error !\n"); exit(0);// } } if (strcmp (data, "exits")==0) { exit (1); } close(sock); } int main(int argc, char const *argv[]) { int serversock,clientsock; struct sockaddr_in echoserver, echoclient; /*if(argc !=2) { fprintf(stderr, "USAGE: echoserver \n"); exit(0); }*/ if((serversock = socket(PF_INET, SOCK_STREAM,IPPROTO_TCP))<0){ Die("Failed"); } memset(&echoserver,0,sizeof(echoserver)); echoserver.sin_family = AF_INET; echoserver.sin_addr.s_addr= htonl(INADDR_ANY); echoserver.sin_port = htons(atoi(argv[1])); if(bind(serversock, (struct sockaddr *) & echoserver,sizeof(echoserver))<0){ Die("Failed"); } if(listen(serversock,MAXPENDING)<0){ Die("Failed"); } while(1) { unsigned int clientlen = sizeof(echoclient); if((clientsock = accept(serversock,(struct sockaddr *) &echoclient, &clientlen))<0){ Die("Failed"); } fprintf(stdout, "Client connected: %s\n", inet_ntoa(echoclient.sin_addr)); fprintf(stdout,"Message from client:"); HandeClient(clientsock); } return 0; } 

客户:

 #include  #include  #include  #include  #include  #include  #include  #define BUFFSIZE 32 /// Client chuyen mot chuoi ki tu, sau khi an enter n gui cho server roi ket thuc void Die(char *mess) { perror(mess); exit(1); } int main(int argc, char *argv[]) { while(1){ int sock; struct sockaddr_in echoserver; char buffer[BUFFSIZE]; unsigned int echolen; int received = 0; if (argc != 3) { fprintf(stderr, "USAGE: TCPecho   \n"); exit(1); } /* Create the TCP socket */ if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { Die("Failed to create socket"); } /* Construct the server sockaddr_in structure */ memset(&echoserver, 0, sizeof(echoserver)); echoserver.sin_family = AF_INET; echoserver.sin_addr.s_addr = inet_addr(argv[1]); echoserver.sin_port = htons(atoi(argv[2])); /* Establish connection */ if (connect(sock,(struct sockaddr *) &echoserver,sizeof(echoserver)) < 0) { Die("Failed to connect with server"); } /* Send the word to the server */ //tao mot chuoi s, chuoi s nhan ki tu tu ban phim, roi chuyen cho phia server char s[100]; fgets(s,100,stdin); echolen = strlen(s); /* send() from client; */ if (send(sock, s, echolen, 0) != echolen) { Die("Mismatch in number of sent bytes"); } /* Receive the word back from the server */ fprintf(stdout, "Message from server: "); while (received < echolen) { int bytes = 0; /* recv() from server; */ if ((bytes = recv(sock, buffer, BUFFSIZE-1, 0)) < 1) { Die("Failed to receive bytes from server"); } received += bytes; buffer[bytes] = '\0'; /* Assure null terminated string */ fprintf(stdout, buffer); } fprintf(stdout, "\n"); close(sock); if(strcmp(s,"exit") == 0) exit(0); } } 

我将代码修改为我认为是您的预期行为。 请注意, execvp()正在原始代码中的末尾而不是开头执行。 我修复了服务器和客户端在其中一个应该发送时尝试接收的几个地方。

我添加了while循环以允许执行命令,直到客户端类型退出。

请参阅代码中的注释。

服务器

 #include  #include  #include  #include  #include  #include  #include  #include  #include  #define MAXPENDING 5 #define BUFFSIZE 2048 #define MAX 2048 void Die(char *mess) { perror(mess); exit(1); } void setup(char inputBuffer[], char *args[], int *background) //Ham xu li (cat) chuoi lenh { const char s[4] = " \t\n"; char *token; token = strtok(inputBuffer, s); int i = 0; while( token != NULL) { args[i] = token; i++; //printf("%s\n", token); token = strtok(NULL,s); } args[i] = NULL; } void HandeClient(int sock){ char buffer[BUFFSIZE]; int received = -1; char data[MAX]; memset(data,0,MAX); while(1) { // this will make server wait for another command to run until it receives exit data[0] = '\0'; if((received = recv(sock, buffer,BUFFSIZE,0))<0){ Die("Failed"); } buffer[received] = '\0'; strcat (data, buffer); if (strcmp(data, "exit")==0) // this will force the code to exit exit(0); /* This block causes server to wait for more data from client when all data are already received. while(received>0) { if(send(sock,buffer, received,0)!= received){ Die("Failed"); } if((received=recv(sock,buffer,BUFFSIZE,0))<0){ Die("Failed"); } buffer[received] = '\0'; strcat (data, buffer); } */ puts (data); char *args[100]; setup(data,args,0); int pipefd[2],lenght; if(pipe(pipefd)) Die("Failed to create pipe"); pid_t pid = fork(); char path[MAX]; if(pid==0) { close(1); // close the original stdout dup2(pipefd[1],1); // duplicate pipfd[1] to stdout close(pipefd[0]); // close the readonly side of the pipe close(pipefd[1]); // close the original write side of the pipe execvp(args[0],args); // finally execute the command } else if(pid>0) { close(pipefd[1]); memset(path,0,MAX); while(lenght=read(pipefd[0],path,MAX-1)){ printf("Data read so far %s\n", path); if(send(sock,path,strlen(path),0) != strlen(path) ){ Die("Failed"); } fflush(NULL); printf("Data sent so far %s\n", path); memset(path,0,MAX); } close(pipefd[0]); //exit(1); removed so server will not terminate } else { printf("Error !\n"); exit(0);// } } /* if (strcmp (data, "exit")==0) { exit (1); } printf("Closing socket\n"); close(sock); */ } int main(int argc, char const *argv[]) { int serversock,clientsock; struct sockaddr_in echoserver, echoclient; unsigned int clientlen = sizeof(echoclient); signal(SIGPIPE, SIG_IGN); // this will allow code to handle SIGPIPE instead of crashing if((serversock = socket(PF_INET, SOCK_STREAM,IPPROTO_TCP))<0){ Die("Failed"); } memset(&echoserver,0,sizeof(echoserver)); echoserver.sin_family = AF_INET; echoserver.sin_addr.s_addr= htonl(INADDR_ANY); echoserver.sin_port = htons(atoi(argv[1])); if(bind(serversock, (struct sockaddr *) & echoserver,sizeof(echoserver))<0){ Die("Failed"); } if(listen(serversock,MAXPENDING)<0){ Die("Failed"); } while(1) { if((clientsock = accept(serversock,(struct sockaddr *) &echoclient, &clientlen))<0){ Die("Failed"); } fprintf(stdout, "Client connected: %s\n", inet_ntoa(echoclient.sin_addr)); fprintf(stdout,"Message from client:"); HandeClient(clientsock); } return 0; } 

客户

  #include  #include  #include  #include  #include  #include  #include  #define BUFFSIZE 2048 void Die(char *mess) { perror(mess); exit(1); } int main(int argc, char *argv[]) { int sock; struct sockaddr_in echoserver; char buffer[BUFFSIZE]; unsigned int echolen; int received = 0; if (argc != 3) { fprintf(stderr, "USAGE: TCPecho   \n"); exit(1); } if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { Die("Failed to create socket"); } memset(&echoserver, 0, sizeof(echoserver)); echoserver.sin_family = AF_INET; echoserver.sin_addr.s_addr = inet_addr(argv[1]); echoserver.sin_port = htons(atoi(argv[2])); if (connect(sock,(struct sockaddr *) &echoserver,sizeof(echoserver)) < 0) { Die("Failed to connect with server"); } char s[100]; while(1) { // to repeat the whole process until exit is typed fgets(s,100,stdin); s[strlen(s)-1]='\0'; //fgets doesn't automatically discard '\n' echolen = strlen(s); /* send() from client; */ if (send(sock, s, echolen, 0) != echolen) { Die("Mismatch in number of sent bytes"); } if(strcmp(s,"exit") == 0) // check if exit is typed exit(0); fprintf(stdout, "Message from server: "); while (received < echolen) { int bytes = 0; /* recv() from server; */ if ((bytes = recv(sock, buffer, echolen, 0)) < 1) { Die("Failed to receive bytes from server"); } received += bytes; buffer[bytes] = '\0'; /* Assure null terminated string */ fprintf(stdout, buffer); } int bytes = 0; // this d {...} while block will receive the buffer sent by server do { buffer[bytes] = '\0'; printf("%s\n", buffer); } while((bytes = recv(sock, buffer, BUFFSIZE-1, 0))>=BUFFSIZE-1); buffer[bytes] = '\0'; printf("%s\n", buffer); printf("\n"); } } 

没有必要循环客户端,因为服务器在发回结果后退出。

你在这一行上有一个分段错误,因为你试图将一个整数传递给strlen

 write(STDOUT_FILENO,pipefd[1],strlen(pipefd[1])); 

你的编译器应至少发出一个警告; gcc做:

 server.c:84: warning: passing argument 1 of 'strlen' makes pointer from integer without a cast /usr/include/string.h:399: note: expected 'const char *' but argument is of type 'int' 

如果打算将pipefd[1]的值写为pipefd[1]作为二进制整数,那么你的意思是这样做吗?

 write(STDOUT_FILENO,&pipefd[1],sizeof(pipefd[1]));