C语言中系统命令的服务器延迟

C语言中系统命令的服务器延迟,c,sockets,system,C,Sockets,System,我有两个程序,一个作为服务器,一个作为客户端。它们的行为应该像您使用ssh连接到远程系统一样。客户端发送一个命令,服务器执行该命令并将输出打印到服务器。虽然我的代码确实做到了这一点,但在第一个命令之后,输出会有一个延迟。例如,如果客户端发送日期,服务器将返回日期。如果客户端再次发送日期,它将打印收到的消息,但不会打印输出。在客户机的第三次输入中,将执行第二个日期,并在客户机上打印,下面是消息:date,依此类推。任何想法都是值得赞赏的 服务器: #include <stdio.h>

我有两个程序,一个作为服务器,一个作为客户端。它们的行为应该像您使用ssh连接到远程系统一样。客户端发送一个命令,服务器执行该命令并将输出打印到服务器。虽然我的代码确实做到了这一点,但在第一个命令之后,输出会有一个延迟。例如,如果客户端发送日期,服务器将返回日期。如果客户端再次发送
日期
,它将打印收到的
消息
,但不会打印输出。在客户机的第三次输入中,将执行第二个日期,并在客户机上打印
,下面是消息:date
,依此类推。任何想法都是值得赞赏的

服务器:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <fcntl.h>
#define MAX_PINS 1
void error(const char *msg){
     perror(msg);
     exit(1);
}

void exec_comm(int sock,int nerror,char buff[]){
     dup2(sock,1);
     dup2(nerror,2);
     if(system(buff)==-1){
          printf("command not found\n");
     }
}
int main(int argc, char *argv[]){
  int sockfd, newsockfd, portno, pid;
  socklen_t clilen;
  char buffer[256];
  char* comm[20],*cbuff;
  struct sockaddr_in serv_addr, cli_addr;
  int n,i,done=0,correct=0;
  char str[INET_ADDRSTRLEN];
  char* args,*pins[MAX_PINS]={"1234"},pin[10];
  FILE* fd;
  int nerror;
     if (argc < 2){
       fprintf(stderr, "No port provided\n");
       exit(1);
     }
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     if (sockfd < 0)
     error("ERROR opening socket");
     memset((char *) &serv_addr, 0, sizeof(serv_addr));
     portno = atoi(argv[1]);
     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(portno);
     if (bind(sockfd,(struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
     error("ERROR on binding");

          listen(sockfd, 5);
          clilen = sizeof(cli_addr);
          newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
          if (newsockfd < 0)
          error("ERROR on accept");
          if (inet_ntop(AF_INET, &cli_addr.sin_addr, str, INET_ADDRSTRLEN) == NULL) {
          fprintf(stderr, "Could not convert byte to address\n");
          exit(1);
          }
          fprintf(stdout, "The client address is :%s\n", str);
while(1){
               bzero(buffer, 256);
               n = read(newsockfd, buffer, 255);
               sscanf(buffer,"%s\n",buffer);
               printf("The message that was read was:\t%s\n",buffer);
               if (n < 0) error("ERROR reading from socket");
               fprintf(fd,"%s\n",buffer);
               if(strcmp(buffer,"exit\n")==0||strcmp(buffer,"exit")==0){
                    printf("Exiting...\n");
                    done=1;
                    break;
               }
               exec_comm(newsockfd,nerror,buffer);
               printf("Here is the message: %s\n", buffer);
               n = write(newsockfd, "message received", 17);
               if (n < 0) error("ERROR writing to socket");
          }

     fclose(fd);
     close(newsockfd);
     close(sockfd);
     return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义最大针脚1
无效错误(常量字符*消息){
佩罗尔(味精);
出口(1);
}
void exec_comm(int sock、int error、char buff[]){
dup2(sock,1);
dup2(n,2);
if(系统(buff)=-1){
printf(“未找到命令\n”);
}
}
int main(int argc,char*argv[]){
int sockfd、newsockfd、端口号、pid;
socklen_t clilen;
字符缓冲区[256];
字符*comm[20],*cbuff;
服务地址中的结构sockaddr\u,cli\u addr;
int n,i,done=0,correct=0;
char str[INET_ADDRSTRLEN];
char*args,*pins[MAX_pins]={“1234”},pin[10];
文件*fd;
内部错误;
如果(argc<2){
fprintf(stderr,“未提供端口”);
出口(1);
}
sockfd=套接字(AF_INET,SOCK_STREAM,0);
if(sockfd<0)
错误(“打开套接字时出错”);
memset((char*)&serv_addr,0,sizeof(serv_addr));
portno=atoi(argv[1]);
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=INADDR_ANY;
serv_addr.sin_port=htons(端口号);
if(bind(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))<0)
错误(“绑定错误”);
听(sockfd,5);
clilen=sizeof(cli_addr);
newsockfd=accept(sockfd,(struct sockaddr*)&cli\u addr,&clilen);
if(newsockfd<0)
错误(“接受错误”);
if(inet\u ntop(AF\u inet,&cli\u addr.sin\u addr,str,inet\u ADDRSTRLEN)==NULL){
fprintf(stderr,“无法将字节转换为地址\n”);
出口(1);
}
fprintf(stdout,“客户端地址为:%s\n”,str);
而(1){
b0(缓冲器,256);
n=读取(newsockfd,缓冲区,255);
sscanf(缓冲区,“%s\n”,缓冲区);
printf(“读取的消息是:\t%s\n”,缓冲区);
如果(n<0)错误(“从套接字读取错误”);
fprintf(fd,“%s\n”,缓冲区);
if(strcmp(缓冲区,“退出”)==0 | | strcmp(缓冲区,“退出”)==0){
printf(“退出…\n”);
完成=1;
打破
}
exec_comm(newsockfd、错误、缓冲区);
printf(“这是消息:%s\n”,缓冲区);
n=写入(newsockfd,“收到消息”,17);
if(n<0)错误(“写入套接字错误”);
}
fclose(fd);
关闭(newsockfd);
关闭(sockfd);
返回0;
}
客户:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error(const char *msg){
     perror(msg);
     exit(0);
}

int main(int argc, char *argv[]){
     int sockfd, portno, n;
     struct sockaddr_in serv_addr;
     struct hostent *server;
     char buffer[256];
     if (argc < 3){
          fprintf(stderr, "usage %s hostname port\n", argv[0]);
          exit(0);
     }
     portno = atoi(argv[2]);
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     if (sockfd < 0)
     error("ERROR opening socket");
     server = gethostbyname(argv[1]);
     if (server == NULL){
          fprintf(stderr, "ERROR, no such host\n");
          exit(0);
     }
     bzero((char *) &serv_addr, sizeof(serv_addr));
     serv_addr.sin_family = AF_INET;
     bcopy((char *)server->h_addr,
     (char *)&serv_addr.sin_addr.s_addr,server->h_length);
     serv_addr.sin_port = htons(portno);
     if (connect(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
     error("ERROR connecting");
     n = write(sockfd, stdin, sizeof(int));
     if (n < 0)
     error("ERROR writing to socket");
     do{
          printf("Please enter the message: ");

          bzero(buffer, 256);
          fgets(buffer, 255, stdin);
          if(strcmp(buffer,"exit\n")==0||strcmp(buffer,"exit")==0){
               printf("Exiting...\n");
               n = write(sockfd, buffer, strlen(buffer));
               if (n < 0)
               error("ERROR writing to socket");
               close(sockfd);
               break;
          }
          n = write(sockfd, buffer, strlen(buffer));
          if (n < 0)
          error("ERROR writing to socket");
          bzero(buffer, 256);
          n = read(sockfd, buffer, 255);
          if (n < 0)
          error("ERROR reading from socket");
          printf("%s\n", buffer);
     }while(1);

     return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
无效错误(常量字符*消息){
佩罗尔(味精);
出口(0);
}
int main(int argc,char*argv[]){
int sockfd,端口号,n;
服务地址中的结构sockaddr\u;
结构主机*服务器;
字符缓冲区[256];
如果(argc<3){
fprintf(stderr,“使用%s主机名端口,\n”,argv[0]);
出口(0);
}
portno=atoi(argv[2]);
sockfd=套接字(AF_INET,SOCK_STREAM,0);
if(sockfd<0)
错误(“打开套接字时出错”);
server=gethostbyname(argv[1]);
如果(服务器==NULL){
fprintf(stderr,“错误,没有这样的主机\n”);
出口(0);
}
bzero((char*)&serv_addr,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
b复制((字符*)服务器->h_地址,
(char*)&服务器地址sin\u addr.s\u addr,服务器->h\u长度);
serv_addr.sin_port=htons(端口号);
if(connect(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))<0)
错误(“连接错误”);
n=写入(sockfd、stdin、sizeof(int));
if(n<0)
错误(“写入套接字时出错”);
做{
printf(“请输入消息:”);
b0(缓冲器,256);
fgets(缓冲区,255,标准输入);
if(strcmp(缓冲区,“退出”)==0 | | strcmp(缓冲区,“退出”)==0){
printf(“退出…\n”);
n=写入(sockfd,buffer,strlen(buffer));
if(n<0)
错误(“写入套接字时出错”);
关闭(sockfd);
打破
}
n=写入(sockfd,buffer,strlen(buffer));
if(n<0)
错误(“写入套接字时出错”);
b0(缓冲器,256);
n=读取(sockfd,缓冲区,255);
if(n<0)
错误(“从套接字读取错误”);
printf(“%s\n”,缓冲区);
}而(1),;
返回0;
}
这就是你的问题。调用
write
不会产生单独的可区分消息,每次调用一条消息。它们产生一个单一的同质字节流(即
SOCK\u stream
中的“流”),没有分隔符

您有分隔命令的换行符,这很好,但是
read
不知道换行符。它只会等到缓冲区满了,或者经过了足够的时间,或者别的什么。你不能控制它

基本上有两种方法可以解决这个问题

  • 逐字符读取(传递长度1),并在看到换行符时立即停止。在缓冲区中累积字符,然后执行它
  • 在固定长度的记录中,在消息本身之前发送每个消息的长度,以便服务器可以安全地读取长度,然后使用它
    n = write(sockfd, buffer, strlen(buffer));