我试图在服务器上运行shell命令,并希望它们在客户端shell中打印..
这意味着当我在客户端shell中键入命令时,该命令应该转到服务器并在服务器内执行并将输出返回给客户端
但是现在面临的唯一问题是我运行的命令如"日期,主机名等"在客户端程序中,它显示预期的输出(客户端 - >服务器 - >客户端)。但是当我跑步的时候" ls"它只显示文件夹中的第一个文件..
作为示例,如果我将五个文件放在一个文件夹中,它只显示文件夹中第一个文件的名称
客户端计划
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#define PORT 1300
#define HOST "127.0.0.1"
#define MAXLINE 1024
main() {
register int s,len;
struct sockaddr_in pin;
struct hostent *hp;
char buff[MAXLINE + 1];
if ((hp=gethostbyname(HOST)) == 0) {
perror("gethostbyname");
exit(1);
}
bzero(&pin, sizeof(pin));
pin.sin_family = AF_INET;
pin.sin_addr.s_addr= ((struct in_addr *) (hp->h_addr)) -> s_addr;
pin.sin_port=htons(PORT);
if ((s=socket(AF_INET,SOCK_STREAM,0)) < 0) {
perror("client:socket");
exit(1);
}
if (connect(s,(struct sockaddr *) &pin,sizeof(pin)) < 0) {
perror("client:connect");
exit(1);
}
char out[20];
strcpy(out,"exit");
while(1){
bzero(buff,MAXLINE+1);
printf("Message> ");
scanf("%s",buff);
if(strcmp(out,buff) == 0){
exit(1);
}
send(s,buff,strlen(buff)+1, 0);
bzero(buff,MAXLINE+1);
read(s,buff,MAXLINE);
printf("Received>");
puts(buff);
}
close(s);
}
这是我的服务器程序
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <time.h>
#include<string.h>
#define PORT 1300
#define MAXLINE 4096
#define COMMAND_LEN 20
#define DATA_SIZE 1512
main() {
register int s,ns;
int len;
struct sockaddr_in sin,pin;
char buff[MAXLINE + 1];
time_t ticks;
struct tm * timeinfo;
FILE *pf;
char command[COMMAND_LEN];
char data[DATA_SIZE];
bzero(&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr= htonl(INADDR_ANY);
sin.sin_port=htons(PORT);
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("server: socket");
exit(1);
}
if (bind(s,(struct sockaddr *)&sin, sizeof(sin)) < 0) {
perror("server:bind");
exit(1);
}
if (listen(s,5) <0) {
perror("server: listen");
exit(1);
}
for(; ;) {
if ((ns = accept(s, (struct sockaddr *)&pin, &len)) < 0) {
perror("server: accept");
exit(1);
}
while(1){
bzero(buff,MAXLINE+1);
read(ns,buff,MAXLINE);
pf=popen(buff,"r");
if(!pf)
{
fprintf(stderr,"could not open for output. \n");
}
fgets(data,DATA_SIZE,pf);
send(ns,data,strlen(data)+1,0);
//puts(buff);
//send(ns,buff,strlen(buff)+1,0);
}
}
close(ns);
close(s);
}
我尝试更改缓冲区大小,但问题仍然存在......
这就是我改变服务器端代码段的方式
bzero(buff,MAXLINE+1);
read(ns,buff,MAXLINE);
pf=popen(buff,"r");
if(!pf)
{
fprintf(stderr,"could not open for output. \n");
}
while(NULL!=fgets(data,DATA_SIZE,pf)){
send(ns,data,strlen(data)+1,0);
}
if(pclose(pf)!=0)
fprintf(stderr,"Error:failed to close command stream \n");
* data ='\0';
//puts(buff);
send(ns,data,1,0);
并且在客户端我将其更改为 下面的代码就在主要方法
之下int idone = 0,ibytes; char * p;
此部分位于客户端程序中,如图所示
while(! idone)
{
ibytes = read (s,buff,MAXLINE);
for (p=buff;(ibytes--);p++)
{
if(! *p)
{idone=1;break;}
putc(*p,stdout);
}
现在当我运行&#34; ls&#34;命令它仍然只显示一个文件,现在完成上述更改后,它甚至不会运行像&#34; date,hostname ...&#34;
这样的命令答案 0 :(得分:3)
在客户端,
read(s,buff,MAXLINE);
无法保证获取服务器发送的所有数据。实际上它可以在返回1个字节后返回。您将不得不在服务器端为消息添加标题,然后确保在收到整个消息之前继续read
。
更不用说在服务器端执行一个fgets()
意味着您只读取popen()中的一行并发送它。你需要继续做fgets()直到EOF。
更不用说你永远不会用pclose
关闭pf。
所以,现在在评论中你试图解决第2点和第2点。第3点pclose
位于错误的位置,但此外,您仍然遇到第1点的问题。在“结果”完成之前,您不知道客户端上要读多少内容。所以我们必须制定一个协议。
现在,您在评论中的代码会使用换行符和ls
向每行发送\0
。让我们改变一下。只允许发送可打印文本,直到完成所有操作,然后发送\0
。
while ( NULL != fgets(data, DATA_SIZE,pf)) {
send( ns, data, strlen( data), 0) ; // not strlen() +1
}
if ( pclose( pf) != 0 ) { perror("Error") ; } // outside the while loop
* data= '\0' ;
send( ns, data, 1, 0 ) ; // send a null
现在,客户端可以整天read()
,并且直到它获得\0
它知道有更多数据。当然要小心一些问题。在打印每条消息之前,您必须将\0
添加到客户端缓冲区。当你在消息中寻找\0
时,你必须确保你没有发现它超过发送的字节数的末尾。
这里的关键是你必须查看read()的返回值,了解实际得到的字节数。
int idone= 0, ibytes ;
char * p;
while ( ! idone )
{
ibytes= read(s,buff,MAXLINE);
for ( p= buff ; ( ibytes -- ) ; p ++ )
{
if ( ! * p ) { idone= 1 ; break ; }
putchar( * p) ;
}
}