停止并等待c,无限超时

时间:2017-11-09 23:05:56

标签: c networking file-transfer packet-loss

我在这个项目上遇到了困难。一切都在工作,除了二进制文件,可能是因为它们相当大,并期望超时。 packetErrorSends类似于send,但它们随机丢弃数据包。我只把它们放在客户端以隔离我的问题。我想要的算法是发送一段文件,如果它接收到,则发送一个' s'并继续阅读并发送发件。如果超时,请发送' e'然后跳入循环,重新发送当前片段并重新开始下一个状态更新。 "虽然"检查状态,决定是继续还是重新发送该片段。问题是,什么时候超时,服务器卡在该循环中重新发送最后一块数据,客户端保持超时并发回(打印报表的目的)任何线索是什么&#39发生了什么?

客户端:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h> 
#include <netdb.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "packetErrorSend.h"
#include <sys/time.h>

ssize_t recvx(int sockfd, void *buf, size_t len) {
  int var = recv(sockfd, buf, len, 0);
  if(var != -1)
  {
    return var;
  } else {
    printf("%s \n","Did not receive.");
    exit(1);
  }
}

int main(int argc, char *argv[])
{
  char buf[MAX_PACKET_DATA_SIZE];
  struct addrinfo hints;
  struct addrinfo *rp, *result;
  int bytes_received =  1;
  int s;
  char *server;
  char *port;
  char *file;
  int fd = -1; //file descriptor
  int bytes_written = 1;
  fd_set readfds;
  struct timeval tv;
  int rv = 0;
  int status;
  char sendStatus[1];
  if (argc==4)
  {
    server = argv[1];
    port = argv[2];
    file = argv[3];
  }
  else
  {
    fprintf(stderr, "invalid # of arguments\n");
    exit(1);
  }

  /* Translate host name into peer's IP address */
  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_INET;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = 0;
  hints.ai_protocol = 0;

  if ((s = getaddrinfo(server, port, &hints, &result)) != 0 )
  {
    fprintf(stderr, "%s: getaddrinfo: %s\n", argv[0], gai_strerror(s));
    exit(1);
  }

  /* Iterate through the address list and try to connect */
  for (rp = result; rp != NULL; rp = rp->ai_next)
  {
    if ((s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) == -1 )
    {
      continue;
    }
    if (connect(s, rp->ai_addr, rp->ai_addrlen) != -1)
    {
      break;
    }
    close(s);
  }

  if (rp == NULL)
  {
    perror("stream-talk-client: connect");
    exit(1);
  }

  freeaddrinfo(result);

  FD_ZERO(&readfds);
  FD_SET(s, &readfds);

  packetErrorSend(s, file, strlen(file)+1, 0);
  tv.tv_sec = 2;
  rv = select(s+1, &readfds, NULL, NULL, &tv);

  if (rv == -1) {
    perror("select"); // error occurred in select()
  } else if (rv == 0) {
    printf("Timeout occurred on filename!  No data after 2 seconds.\n");
    close(s);
    exit(0);
  } else {
    status = recvx(s,buf,1);
  }
  if(status == 0 || buf[0] == 'e')
  {
    fprintf(stderr, "Server Error: unable to access file %s \n", file);
    close(s);
    exit(0);
  }

  if(buf[0] == 's')
  {
    fd =open(file, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
    if(fd == -1)
    {
      fprintf(stderr,"%s \n","Client Error: Open failed");
      close(s);
      exit(0);
    }

    FD_ZERO(&readfds);
    FD_SET(s, &readfds);
    bytes_received = MAX_PACKET_DATA_SIZE;
    // while(bytes_received >= MAX_PACKET_DATA_SIZE)
    while(bytes_received > 0)
    {
      tv.tv_sec = 3;
      rv = select(s+1, &readfds, NULL, NULL, &tv);
      if (rv == -1) {
        perror("select");
      } else if (rv == 0) {
        printf("bytes_received in timeout %d \n", bytes_received );
        printf("Timeout occurred!  No data after 3 seconds.\n");
        sendStatus[0] = 'e';
        send(s,sendStatus,1,0);
      } else {
        bytes_received = recvx(s, buf, MAX_PACKET_DATA_SIZE);
        printf("%d\n", bytes_received);
        sendStatus[0]='s';
        packetErrorSend(s,sendStatus,1,0);

      }

      bytes_written = write(fd,buf,bytes_received);
      if(bytes_written == -1)
      {
        fprintf(stderr,"%s \n", "Client Error: Write error");
        break;
      }
    }

    if(bytes_received == -1)
    {
      fprintf(stderr,"%s \n", "Client Error: Error receiving file");
      exit(0);
    }
    if(close(fd) != 0)
    {
      printf("%s \n", "Client Error: File did not close successfully");
      exit(0);
    }
    close(s);
  }
  return 0;

}

服务器:

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include "packetErrorSend.h"
#include <sys/time.h>

#define SERVER_PORT "5432"
#define MAX_PENDING 5

int main(int argc, char *argv[])
{
  struct addrinfo hints;
  struct addrinfo *rp, *result;
  char file[MAX_PACKET_DATA_SIZE];
  int s, new_s;
  int bytes_transferred = 0;
  int fd; //file descriptor
  char status[1];

  /* Build address data structure */
  memset(&hints, 0, sizeof(struct addrinfo));
  hints.ai_family = AF_INET;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_PASSIVE;
  hints.ai_protocol = 0;
  hints.ai_canonname = NULL;
  hints.ai_addr = NULL;
  hints.ai_next = NULL;

  /* Get local address info */
  if ((s = getaddrinfo(NULL, argv[1], &hints, &result)) != 0 )
  {
    fprintf(stderr, "%s: getaddrinfo: %s\n", argv[0], gai_strerror(s));
    exit(1);
  }

  /* Iterate through the address list and try to perform passive open */
  for (rp = result; rp != NULL; rp = rp->ai_next)
  {
    if ((s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) == -1 )
    {
      continue;
    }

    if (!bind(s, rp->ai_addr, rp->ai_addrlen))
    {
      break;
    }
    close(s);
  }
  if (rp == NULL)
  {
    perror("stream-talk-server: bind");
    exit(1);
  }
  if (listen(s, MAX_PENDING) == -1)
  {
    perror("stream-talk-server: listen");
    close(s);
    exit(1);
  }

  freeaddrinfo(result);

  /* Wait for connection, then receive and print text */
  while(1)
  {
    for(int i = 0; i < sizeof(file); i++)
    {
      file[i] = '\0';
    }

    if ((new_s = accept(s, rp->ai_addr, &(rp->ai_addrlen))) < 0)
    {
      perror("stream-talk-server: accept");
      close(s);
      exit(0);
    }

    if ((bytes_transferred = recv(new_s,file,sizeof(file),0)) > 0)
    {

      fd = open(file,O_RDONLY);
      if(fd < 0)
      {
        perror("open");
        status[0] = 'e';
        send(new_s,status,1,0);
        close(new_s);
        exit(0);
      }
      status[0] = 's';
      send(new_s,status,1,0);
      int datasent = 0;
      bytes_transferred = 1;
      while(bytes_transferred  > 0)    
      {
        status[0] = s;
        bytes_transferred = read(fd,file,MAX_PACKET_DATA_SIZE);
        printf("%d\n",bytes_transferred);
        datasent = send(new_s,file,bytes_transferred,0);
        if (datasent < 0)
        {
          perror("send");
          break;
        }
        recv(new_s,status,1,0);

        printf("before while: %c \n", status[0]);
        while(status[0] == 'e')
        {
          recv(new_s,status,1,0);
          send(new_s,file,bytes_transferred,0);
          printf("in while: %c \n", status[0]);
        }
      }
      if (bytes_transferred == 0)
      {
        break;
      }
      else if(bytes_transferred == -1)
      {
        perror("read");
        close(new_s);
        exit(0);
      }
    }
  }
  close(fd);
  close(new_s);

  return 0;
}

0 个答案:

没有答案