我试图在服务器上运行shell命令,并希望将它们打印到客户端shell中。。
这意味着当我在客户机shell中键入一个命令时,该命令应该转到服务器并在服务器内部执行,然后将输出返回给客户机
但iam现在面临的唯一问题是,当我在客户机程序中运行“Date,hostname etc”等命令时,它会显示预期的输出(客户机->服务器->客户机)。但当我运行“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);
在客户端我把它改成
下面的代码就在main方法下面
智力密度=0,单位为磅;
字符*p;
此部分在客户程序中,如图所示
while(! idone)
{
ibytes = read (s,buff,MAXLINE);
for (p=buff;(ibytes--);p++)
{
if(! *p)
{idone=1;break;}
putc(*p,stdout);
}
现在,当我运行“ls”命令时,它仍然只显示一个文件,现在在执行上述更改之后,它甚至不运行“date,hostname…”这样的命令
最佳答案
在客户端,
read(s,buff,MAXLINE);
无法保证获取服务器发送的所有数据。实际上,它可以在返回1字节后返回。您必须在服务器端为邮件添加一个标题,然后确保在接收到整个邮件之前一直
read
。更不用说在服务器端执行一个
fgets()
意味着您只从popen()中读取一行并发送它。你需要一直做fgets()直到结束。更不用说你从来没有用
pclose
关闭pf。所以,现在在评论中,你试着解决第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) ;
}
}
关于c - 客户端和服务器通信,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20437327/