简体   繁体   English

不会从服务器到客户端接收完整数据(unix-C)

[英]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. 我在服务器中安装了Unix shell,该shell应该将输出发送到客户端,然后将其打印出来。 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. 我尝试了几种不同的方法来获取完整的输出,但是即使我在recv中使用while循环也应该能够接收所有内容,但我只能得到3-5个字母。

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; 考虑到您获得的流量不是全部,而是两个break; ,也许一个潜在的问题是两次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. 第一次进入时, 无论是否有更多数据,它都会在一个或另一个分支中退出while循环。

You might consider two additional things: 您可能会考虑另外两件事:
1) using an alternate call structure. 1)使用备用呼叫结构。 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(,,,); 2)在成功send(,,,);之间留出很小的延迟(几分之一秒send(,,,); and calling recv(,,,) . 并调用recv(,,,)

EDIT example of using terminating character with sockets 与套接字一起使用终止字符的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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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