【问题标题】:Server delay on system command in CC中系统命令的服务器延迟
【发布时间】:2020-01-25 10:55:20
【问题描述】:

我有两个程序,一个充当服务器,一个充当客户端。他们应该表现得就像您正在使用 ssh 连接到远程系统一样。客户端发送命令,服务器执行命令并将输出打印到服务器。虽然我的代码正是这样做的,但在第一个命令之后输出会有延迟。例如,如果客户端发送date,服务器将返回日期。如果客户端再次发送date,它将打印message was received,而不是输出。在客户端的第三次输入时,第二个日期将被执行并打印在客户端Here is the message: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;
}

客户:

#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;
}

【问题讨论】:

  • 为什么服务器会忽略第一次读取加载的数据——循环之前的那个?
  • 糟糕,忘记删除了。我现在删除了它。

标签: c sockets system


【解决方案1】:
n = write(sockfd, buffer, strlen(buffer));

这就是你的问题。对write 的调用不会产生单独的可区分消息,每次调用一条消息。它们会产生一个没有分隔符的同质字节流(即SOCK_STREAM 中的“流”)。

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

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

  1. 逐个字符读取(传递长度为 1)并在看到换行符后立即停止。将字符累加到缓冲区中,然后执行。
  2. 在消息本身之前发送每条消息的长度,在一个固定长度的记录中,以便服务器可以安全地读取长度,然后使用它来读取消息本身。

【讨论】:

  • 我很确定有很多重复项,但我没有太多时间找到合适的,只写一个新答案更容易。如果您找到更好的答案,请随时链接。
  • 我已经通过在读取套接字时将sscanf(buffer,"%s\n",buffer); 添加到我的服务器来解决此问题,但不幸的是,这并不能解决我的问题。
  • @Azzarian 你已经解决了你的问题,但这并没有解决你的问题。明白了。也许这不是你的问题?
  • 我的意思是我用换行符解决了你暗示的问题,但我在这个线程上指的问题仍然存在。
  • 不,抱歉。看来你没听懂我在说什么。我不是说你有换行问题。我并不是说删除换行符会解决您的问题。 (您可能无论如何都应该删除它们,但这是一个完全不同的问题。)请尝试阅读实际写入的内容。
猜你喜欢
  • 1970-01-01
  • 2014-10-06
  • 1970-01-01
  • 1970-01-01
  • 2018-02-28
  • 1970-01-01
  • 2018-09-18
  • 1970-01-01
  • 2021-02-10
相关资源
最近更新 更多