简体   繁体   中英

Won't receive full data from server to client (unix - C)

I got a Unix shell in a server which should send the output the the client and then be printed out. I have tried several different methods to get the full output but i only get 3-5 letters even though I use a while-loop in recv which should be able to receive everything.

The server prints out the whole output but the client doesn't receive the whole data.

Server code:

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1


#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/wait.h>
#define SOCK_PATH "echo_socket"
#define ORDLANGD 30
#define die(e) do { fprintf(stderr, e); exit(EXIT_FAILURE); } while (0);

void byt(char *foo);
void lasIn(char *a1, char *argv[]);

static void pSigHandler(int signo){
    switch (signo) {
            case SIGTSTP:
            printf("TSTP");
            fflush(stdout);
            break;
    }
}

int main(void)
{
  int s, s2, t, len, newsockfd;
  struct sockaddr_un local, remote;
  char str[100];
  char *argv[7];
  char foo[4096];
  int link[2];

  if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
    perror("socket");
    exit(1);
  }

  local.sun_family = AF_UNIX;
  strcpy(local.sun_path, SOCK_PATH);
  unlink(local.sun_path);
  len = strlen(local.sun_path) + sizeof(local.sun_family);
  if (bind(s, (struct sockaddr *)&local, len) == -1) {
    perror("bind");
    exit(1);
  }

  if (listen(s, 5) == -1) {
    perror("listen");
    exit(1);
  }

    struct sigaction psa;
    psa.sa_handler = pSigHandler;
    sigaction(SIGTSTP, &psa, NULL);

  for(;;) {
    int done, n;
    printf("Waiting for a connection...\n");
    t = sizeof(remote);
    if ((s2 = accept(s, (struct sockaddr *)&remote, &t)) == -1) {
      perror("accept");
      exit(1);
    }

    printf("Connected.\n");

        pid_t pid;
        pid = fork();
        if (pid < 0)
        {
            perror("ERROR on fork");
        exit(1);
        }

                if (pid == 0)
        {
            /* This is the client process */
            close(s);

                                done = 0;
                    do {
                      n = recv(s2, str, 100, 0);
                      if (n <= 0) {
                    if (n < 0) perror("recv");
                    done = 1;
                      }

                 lasIn(str, argv);
                 if ((strcmp(argv[0], "exit")) == 0){
                    exit(0);
                 }
                 else if ((strcmp(argv[0], "cd")) == 0){
                    if ((chdir(argv[1])) != 0){
                        printf("Gar inte att byta katalog\n");
                        }
                 }

                pid_t pid;

              if (pipe(link)==-1)
                die("pipe");

              if ((pid = fork()) == -1)
                die("fork");

              if(pid == 0) {

                dup2 (link[1], STDOUT_FILENO);
                close(link[0]);
                execvp(argv[0], argv);
                sleep (1);
                exit(0);

              } else {

                close(link[1]);
                read(link[0], foo, sizeof(foo));
                printf("\n\n%s\n\n", foo);

                wait(NULL);

              }

                      if (!done)
                      {

                    if (send(s2, foo, n, 0) < 0) {
                      perror("send");
                      done = 1;
                    }
                      }
                    } while (!done);




        }
        else
        {
            close(s2);
        }


  }

  return 0;
}


void lasIn(char *a1, char *argv[]){
  int i;
  argv[0] = strtok(a1, " \n");
  for(i = 1; i < 6; i = i++) {
        argv[i] = strtok(NULL, " \n");
        if (argv[i] == NULL)
        break;
  }
  argv[6] = NULL;
}

Client code:

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

#define SOCK_PATH "echo_socket"


int main(void)
{

  int s, t, len;
  struct sockaddr_un remote;
  char str[100];

  if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
    perror("socket");
    exit(1);
  }

  printf("Trying to connect...\n");

  remote.sun_family = AF_UNIX;
  strcpy(remote.sun_path, SOCK_PATH);
  len = strlen(remote.sun_path) + sizeof(remote.sun_family);
  if (connect(s, (struct sockaddr *)&remote, len) == -1) {
    perror("connect");
    exit(1);
  }

  printf("Connected.\n");

  while(printf("> "), fgets(str, 100, stdin), !feof(stdin)) {
    if (send(s, str, strlen(str), 0) == -1) {
      perror("send");
      exit(1);
    }

        while(1)
        {
            memset(str ,0 , 100);  //clear the variable
            if(recv(s , str , 100 , 0) < 0)
            {
                break;
            }
            else
            {
                printf("%s" , str);
                break;

            }
        }
  }

  close(s);

  return 0;
}

Given that you are getting some, not all of your expected traffic, perhaps one potential problem is the two break; statments in your code section:

while(1)
{
    memset(str ,0 , 100);  //clear the variable
    if(recv(s , str , 100 , 0) < 0)
    {
        break;//here
    }
    else
    {
        printf("%s" , str);
        break;//and here

    }
}

The first time in, it will either break out of the while loop in one or the other branches, regardless of whether there is more data.

You might consider two additional things:
1) using an alternate call structure. Something like:

while(recv(s , str , 100 , 0) > 0)
{
   ...
}
//do some error checking here  

2) put a small (fraction of a second) delay between leaving a successful send(,,,); and calling recv(,,,) .

EDIT example of using terminating character with sockets

numBytesReceived = recv(irdaCommSocket, recvBuf, readBufsize, 0);
while(strstr(recvBuf, "%") == NULL)//uniques terminating character (use anything, including `\n`)
{
    if (numBytesReceived < 0) return WSAGetLastError();//windows specific, change error handling for linux
    strncpy(bufptr, recvBuf, readBufsize);
    *pNumBytes += numBytesReceived;
    numBytesReceived = recv(irdaCommSocket, recvBuf, readBufsize, 0);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM