STDOUT не отправляет все данные через сокет в C ++ - PullRequest
0 голосов
/ 28 апреля 2020

Я новичок в программировании сокетов на C ++ и UNIX. Я работаю на простой серверной и клиентской программе. Клиентская программа считывает данные из файла .txt, который содержит хост и количество пингов для отправки. Клиент отправляет строку на сервер, где сервер анализирует строку и запускает команду ping. Затем сервер отправляет вывод обратно клиенту. Проблема у меня в том, что сервер отправляет только 2 строки вывода ping, а не все. Я не уверен, если это проблема в моем коде сервера или кода клиента.

Код сервера:

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <string>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <sysexits.h>

using namespace std;
#define MAXLINE 2048 /*max text line length*/
#define LISTENQ 8 /*maximum number of client connections */

int main (int argc, char **argv)
{
  int listenfd, connfd, n;
  socklen_t clilen;
  char buf[MAXLINE];
  struct sockaddr_in cliaddr, servaddr;
  int portNumber = atoi(argv[1]);
  char *ch;
  char hostName[50];
  char pingsToSend[50];
  char *pingArgArray[5];
  pid_t cpid;
  int status;
  int i;

  //creation of the socket
  listenfd = socket (AF_INET, SOCK_STREAM, 0);

  //preparation of the socket address
  servaddr.sin_family = AF_INET;
  servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  servaddr.sin_port = htons(portNumber);

  bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));

  listen(listenfd, LISTENQ);

  printf("%s%d\n","Server - Start with Port=",portNumber);
  printf("%s%d\n","\tThe server PID is:",getpid());

  for ( ; ; ) {
    clilen = sizeof(cliaddr);
    connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen);

    while ( (n = recv(connfd, buf, MAXLINE,0)) > 0)  {
      printf("\n%s","Server - Input Data received: ");
      puts(buf);

      //Parse each line of input file
      ch = strtok(buf, " ");
      strcpy(hostName,ch);
      ch = strtok(NULL, " ");
      strcpy(pingsToSend,ch);

      //Get rid of deprecated conversion from string constant to 'char*' error
      string binCommand = "/bin/ping";
      string dashC = "-c";
      char * arrayBinCommand = new char [binCommand.length()+1];
      strcpy(arrayBinCommand,binCommand.c_str());
      char * arrayDashC = new char [binCommand.length()+1];
      strcpy(arrayDashC,dashC.c_str());

      //Array of arguments to pass to execv
      pingArgArray[0] = arrayBinCommand;
      pingArgArray[1] = hostName;
      pingArgArray[2] = arrayDashC;
      pingArgArray[3] = pingsToSend;
      pingArgArray[4] = NULL;

      if (cpid == 0){
        fprintf(stdout,"Server - Fork child process");
        fprintf(stdout,"\nServer - Sent results of the ping comand to the client via socket");
        close(listenfd);
        dup2(connfd,STDOUT_FILENO);
        dup2(connfd,STDERR_FILENO);
        close(connfd);
        execvp(pingArgArray[0],pingArgArray);
      }
    }

    if (n < 0) {
      perror("Read error");
      exit(1);
    }
  }
  //close listening socket
  close(listenfd);
}

Код клиента:

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <fstream>
#include <unistd.h>
#include <sys/wait.h>
using namespace std;

#define MAXLINE 2048 /*max text line length*/
int main(int argc, char **argv)
{
  int sockfd;
  struct sockaddr_in servaddr;
  char sendline[MAXLINE], recvline[MAXLINE];
  int portNumber = atoi(argv[2]);
  int serverIp = atoi(argv[1]);
  string line;
  ifstream pingArgumentsIn("pingData.txt");

  //basic check of the arguments
  if (argc !=3) {
    perror("Usage: TCPClient <IP address of the server> <port # of the server>");
    exit(1);
  }

  printf("%s%d%s%d\n","Client - Start with IP=",serverIp," and Port=",portNumber);
  printf("%s%d\n","\tThe client PID is:",getpid());

  //Catch error if file is not found or cant be opened
  if (!pingArgumentsIn){
    cout << "File could not be opened\n";
    return 0;
  }

  //Create a socket for the client
  //If sockfd<0 there was an error in the creation of the socket
  if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) <0) {
    perror("Client - Problem in creating the socket");
    exit(2);
  }

  //Creation of the socket
  memset(&servaddr, 0, sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_addr.s_addr= inet_addr(argv[1]);
  servaddr.sin_port =  htons(portNumber); //convert to big-endian order

  //Connection of the client to the socket
  if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr))<0) {
    perror("Client - Problem in connecting to the server");
    exit(3);
  } else {
    printf("\n%s", "Client - Connected to server");
  }

  while (getline(pingArgumentsIn,line)){
    printf("\n%s%s","Client - Input data is: ",line.c_str());
    printf("\n%s", "Client - Sending input data to the server");

    send(sockfd, line.c_str(), strlen(line.c_str()), 0);

    if (recv(sockfd, recvline, MAXLINE,0) == 0){
      //error: server terminated prematurely
      perror("Client - The server terminated prematurely");
      exit(4);
    }
    printf("\n%s", "Client - Received output from the server via socket: ");
    printf("\n");
    fputs(recvline, stdout);

  }
  exit(0);
}

Здесь показан текущий вывод Я получаю:

Client - Received output from the server via socket:
PING www.google.com (172.217.12.68) 56(84) bytes of data.
64 bytes from dfw28s05-in-f4.1e100.net (172.217.12.68): icmp_seq=1 ttl=48 time=1.92 ms

Когда это то, что я ожидаю:

Client - Received output from the server via socket:
PING www.google.com (172.217.12.68) 56(84) bytes of data.
64 bytes from dfw28s05-in-f4.1e100.net (172.217.12.68): icmp_seq=1 ttl=48 time=1.96 ms
64 bytes from dfw28s05-in-f4.1e100.net (172.217.12.68): icmp_seq=2 ttl=48 time=1.99 ms
64 bytes from dfw28s05-in-f4.1e100.net (172.217.12.68): icmp_seq=3 ttl=48 time=1.91 ms
64 bytes from dfw28s05-in-f4.1e100.net (172.217.12.68): icmp_seq=4 ttl=48 time=1.96 ms
64 bytes from dfw28s05-in-f4.1e100.net (172.217.12.68): icmp_seq=5 ttl=48 time=1.96 ms

--- www.google.com ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4004ms
rtt min/avg/max/mdev = 1.915/1.959/1.992/0.054 ms
...