【问题标题】:Won't receive full data from server to client (unix - C)不会从服务器接收到客户端的完整数据(unix - C)
【发布时间】:2014-02-24 20:03:59
【问题描述】:

我在服务器中有一个 Unix shell,它应该将输出发送到客户端,然后被打印出来。我尝试了几种不同的方法来获得完整的输出,但我只得到 3-5 个字母,即使我在 recv 中使用了一个应该能够接收所有内容的 while 循环。

服务器打印出整个输出,但客户端没有接收到全部数据。

服务器代码:

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

客户端代码:

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

【问题讨论】:

    标签: c shell unix client-server


    【解决方案1】:

    鉴于您获得了一些(而非全部)预期流量,可能一个潜在问题是您的代码部分中的两个break; 语句:

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

    第一次进入时,它会在一个或另一个分支中跳出 while 循环,无论是否有更多数据。

    您可以考虑另外两件事:
    1)使用替代调用结构。类似的东西:

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

    2) 在离开成功的send(,,,); 和调用recv(,,,) 之间存在一小段(几分之一秒)延迟。

    EDIT 使用套接字终止字符的示例

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

    【讨论】:

    • 我尝试过使用 while(recv(s , str , 100 , 0) > 0) 但该语句从未实现,它永远不会进入 while 循环。
    • 同理 if(recv(s , str , 100 , 0)
    • 我也尝试过在客户端和服务器中都设置 sleep (4) 但没有帮助
    • 发现错误,在服务器中发送代码是 if (send(s2, foo, n, 0)
    • @user3344447 - (抱歉,不得不去一段时间)那么,发现并修复了服务器错误,你还好吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-29
    • 1970-01-01
    • 2021-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多