⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 send_receive.c

📁 飞鸽传书协议的linux实现,使用多线程实现的
💻 C
📖 第 1 页 / 共 2 页
字号:
    if (traverseDir(fSock, fullpath, snd)<0)      return -1;  }  ptr[-1] = '\0'; //还原fullname  snd(fSock, ".", 0, 3);  if (closedir(dp) < 0)  {    printf("\nDir: close error.\n");    return -1;  }  return 0;}//列举待发送文件int listSFiles(gsNode **list, gsNode *gs, int size){  filenode *curFile;  int tmp=0;  while ((gs!=NULL)&&(tmp<size))  {    if ((gs->cancelled==0))    {      *list++ = gs;      tmp++;    }    gs = gs->next;  }    return tmp;  }//取消文件传输int ceaseSend(){  gsNode *gsList[CAPACITY], *cur;  int tmp, index, count;  char buf[FILENAME];  filenode *curFile;  while(1)  {    pthread_mutex_lock(&sendFMutex);    count = listSFiles(gsList, sendFHead.next, sizeof(gsList)/sizeof(gsList[0])-1);    pthread_mutex_unlock(&sendFMutex);        if (count == 0)      return 0;    else    {      printf("\n++++++++++++++++++++\n");      printf("Files to send:\n");      for(tmp=1;tmp<=count;tmp++)      {        printf("%d. ", tmp);        curFile = (*(gsList+tmp-1))->fileList.next;        while (curFile!=NULL)        {          printf("%s ", curFile->fileName);          curFile = curFile->next;        }        printf("\n");      }      printf("++++++++++++++++++++\n");    }    index = inputNo(1, count, 1,                    "Which file(s) to cancel?(Ctrl+D to quit)\nNumber[1]:");    if (index<0)      return -1;    pthread_mutex_lock(&sendFMutex);    (*(gsList+index-1))->cancelled = 1;    if ((*(gsList+index-1))->tcpSock>=0)      shutdown((*(gsList+index-1))->tcpSock, SHUT_RDWR);    pthread_mutex_unlock(&sendFMutex);  }}//////////////////////////////////////////////////////文件接收//选择要接收的文件int recvFiles(){  gsNode *gsList[CAPACITY], *cur;  int tmp, index, count;  char buf[FILENAME];  struct stat dirAttr;  pthread_t gFile;  filenode *curFile;  pthread_attr_t attr;    while(1)  {    pthread_mutex_lock(&getFMutex);    count = listGFiles(gsList, getFHead.next, sizeof(gsList)/sizeof(gsList[0])-1);    pthread_mutex_unlock(&getFMutex);        if (count == 0)      return -1;    else    {      printf("\n++++++++++++++++++++\n");      printf("Files to get:\n");      for(tmp=1;tmp<=count;tmp++)      {        printf("%d. ", tmp);        curFile = (*(gsList+tmp-1))->fileList.next;        while (curFile!=NULL)        {          printf("%s ", curFile->fileName);          curFile = curFile->next;        }        printf("\n");      }      printf("++++++++++++++++++++\n");    }    index = inputNo(1, count, 1,                    "Which file(s) to get?(Ctrl+D to quit)\nNumber[1]:");    if (index<0)      return -1;        while(1)    {      printf("Where do you want to save?(Ctrl+D to quit)\nTarget dir[.]:");      if (fgets(buf, sizeof(buf), stdin)==NULL)        return -1;      transfStr(buf, 0); //去除前后空白字符            if (buf[0]=='\0')      {        buf[0]='.';        buf[1]='\0';      }            if ((stat(buf, &dirAttr)<0) ||          !S_ISDIR(dirAttr.st_mode) ||          (access(buf, W_OK)<0))        printf("Invalid directory. Please input again.\n");      else break;    }        cur = *(gsList+index-1);    tmp = strlen(buf);    pthread_mutex_lock(&getFMutex);    if (cur->cancelled == 0)    {      cur->targetDir = (char*)malloc(tmp+1);      strncpy(cur->targetDir, buf, tmp+1);      cur->transferring = 1;    }    pthread_mutex_unlock(&getFMutex);    pthread_attr_init(&attr);    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);    pthread_create(&gFile, &attr, &getData, cur);  }}//文件接收线程void* getData(void* option){  gsNode *gList = (gsNode *)option;  filenode *head=&gList->fileList, *cur;  int fileType, tmp;  command com;  printf("\nStart getting files.\n");  while((cur=head->next) != NULL)  {    fileType = cur->fileType & 0x03;    switch (fileType)    {    case 1:      tmp=getFile(cur, gList);      break;    case 2:      tmp=getDir(cur, gList);      break;    default:      tmp = -1;      printf("\nUnsupported file type.\n%s fails to be transfered.\n", cur->fileName);      break;    }        if (tmp<0)    {      initCommand(&com, IPMSG_RELEASEFILES);      snprintf(com.additional, sizeof(com.additional), "%d", gList->packetNo);      memcpy(&com.peer, &gList->peer, sizeof(com.peer));      sendMsg(&com);      pthread_mutex_lock(&getFMutex);      gList->cancelled = 1;      gList->transferring = 0;      pthread_mutex_unlock(&getFMutex);      printf("\n%s fails to be transfered.\n", cur->fileName);      return NULL;    }        printf("\n%s is transferred.\n", cur->fileName);    head->next = cur->next;    free(cur);  }  pthread_mutex_lock(&getFMutex);  gList->cancelled = 1; //其实是已经完成  gList->transferring = 0;  pthread_mutex_unlock(&getFMutex);    printf("File reception done.\n");}//接收文件int getFile(void* option, gsNode *gList){  int sockfd, readBytes;  char buf[COMLEN];  char recvs[RECFRG];  filenode *head = (filenode*)option;  command com;  struct sockaddr_in peer;  long fileSize, offset=0;  FILE* recvFile;  initCommand(&com, IPMSG_GETFILEDATA);  //Regular file  snprintf(com.additional, MSGLEN, "%x:%x:%x", gList->packetNo, head->fileNo, offset);    sockfd = socket(AF_INET, SOCK_STREAM, 0);  bzero(&peer, sizeof(peer));  peer.sin_family = AF_INET;  peer.sin_port = htons(IPMSG_DEFAULT_PORT);  memcpy(&peer.sin_addr, &gList->peer.sin_addr, sizeof(peer.sin_addr));    if (connect(sockfd, (struct sockaddr*)&peer, sizeof(peer))<0)  {    printf("File connect error.\n");    return -1;  }    msgCreater(buf, &com, sizeof(buf));  if (writen(sockfd, buf, strlen(buf)+1)<0)    return -1;  sscanf(head->fileSize, "%x", &fileSize);  if ((recvFile = fopen(head->fileName, "w+")) == NULL)  {    printf("getFile: file create error.\n");    return -1;  }  while (fileSize>0)  {    readBytes = fileSize < RECFRG ? fileSize:RECFRG;    if ((readBytes = readn(sockfd, recvs, readBytes))<0) //RECFRG    {      printf("getFile: data transfer error.\n");      return -1;    }        fwrite(recvs, 1, readBytes, recvFile);    fileSize -= readBytes;  }  fclose(recvFile);    close(sockfd);  return 0;}//接收文件夹时分析,头部int parseHeader(filenode *pfn, char * recvs){  char *strhead, *strtmp, gMsg[FILENAME];  int i=0;    strhead = recvs;  while (i<3) //分析前3段  {    strtmp = strchr(strhead, ':');    if (strtmp == NULL)      return -1;    *strtmp = '\0';    switch (i)    {    case 0:            strncpy(gMsg, strhead, sizeof(gMsg));      delColon(gMsg, sizeof(gMsg));      if (utf8)        g2u(gMsg, sizeof(gMsg),            pfn->fileName, sizeof(pfn->fileName));      else strncpy(pfn->fileName, gMsg, sizeof(pfn->fileName));      break;    case 1:      //sscanf(strhead, "%x", &pfn->fileSize);      strncpy(pfn->fileSize, strhead, sizeof(pfn->fileSize));      break;    case 2:      sscanf(strhead, "%x", &pfn->fileType);      break;      //case 3: //进行了简化      // strncpy(pfh->h14, strhead+3, sizeof(pfh->h14));      //break;      //case 4:      //strncpy(pfh->h16, strhead+3, sizeof(pfh->h16));      //break;    default:      break;    }    strhead = strtmp+1;    i++;  }  strncpy(pfn->otherAttrs, strhead, sizeof(pfn->otherAttrs));    return 0;}//接收文件夹int getDir(void *option, gsNode *gList){  int sockfd, readBytes, headerSize, fileType, dirDepth=0, tmp;  char buf[COMLEN], recvs[RECFRG], hSize[HSIZE], fullPath[2*FILENAME];  filenode *head = (filenode*)option, *cur, fn;  command com;  struct sockaddr_in peer;  long  offset=0, fileSize;  FILE* recvFile;  strncpy(fullPath, gList->targetDir, sizeof(fullPath));    initCommand(&com, IPMSG_GETDIRFILES); //Direcotry    snprintf(com.additional, MSGLEN, "%x:%x:%x", gList->packetNo, head->fileNo, offset);    sockfd = socket(AF_INET, SOCK_STREAM, 0);  bzero(&peer, sizeof(peer));  peer.sin_family = AF_INET;  peer.sin_port = htons(IPMSG_DEFAULT_PORT);  memcpy(&peer.sin_addr, &gList->peer.sin_addr, sizeof(peer.sin_addr));    if (connect(sockfd, (struct sockaddr*)&peer, sizeof(peer))<0)  {    printf("File connect error.\n");    return -1;  }  msgCreater(buf, &com, sizeof(buf));    if (writen(sockfd, buf, strlen(buf)+1)<0)    return -1;    do  {    tmp = strlen(fullPath);    if (tmp+1>=sizeof(fullPath))    {      printf("getDir: target directory is too lang.\n");      return -1;    }    if (fullPath[tmp-1]!='/')    {      fullPath[tmp] = '/';      fullPath[tmp+1] = '\0';    }      readBytes = readDelimiter(sockfd, hSize, HSIZE, ':');    sscanf(hSize, "%x", &headerSize);    if (headerSize<=0 || headerSize<=readBytes || headerSize>RECFRG) //保护、防止溢出      return -1;    readn(sockfd, recvs, headerSize-readBytes);    recvs[headerSize-readBytes]='\0';        if (parseHeader(&fn, recvs)<0)    {      printf("getDir: Parse protocol failed.\n");      return -1;    }        switch (fn.fileType & 0x03)    {    case IPMSG_FILE_REGULAR:      strncat(fullPath, fn.fileName, sizeof(fullPath)-tmp-1);      if ((recvFile = fopen(fullPath, "w+")) == NULL)      {        printf("Open error.\n");        return -1;      }            sscanf(fn.fileSize, "%x", &fileSize);      while (fileSize>0)      {        readBytes = fileSize < RECFRG ? fileSize:RECFRG;        if ((readBytes = readn(sockfd, recvs, readBytes))<0) //RECFRG        {          printf("File read error.\n");          return -1;        }                fwrite(recvs, 1, readBytes, recvFile);        fileSize -= readBytes;      }      fclose(recvFile);      getParentPath(fullPath, sizeof(fullPath));      break;          case IPMSG_FILE_DIR:      strncat(fullPath, fn.fileName, sizeof(fullPath)-tmp-1);      tmp = strlen(fullPath);      if (tmp+1>=sizeof(fullPath))      {        printf("getDir: target directory is too lang.\n"               "Filename(%s) has been truncated.\n", fn.fileName);        fullPath[tmp-1] = '/';      }      else      {        fullPath[tmp] = '/';        fullPath[tmp+1] = '\0';      }            if (mkdir(fullPath, S_IRUSR|S_IWUSR|S_IXUSR))      {        printf("getDir: mkdir failed.\n");        return -1;      }            dirDepth++;      break;          case IPMSG_FILE_RETPARENT:      getParentPath(fullPath, sizeof(fullPath));      dirDepth--;      break;          default:      printf("Unsupported file type.\n");      break;    }      }while(dirDepth>0);  //close(sockfd);  shutdown(sockfd, SHUT_RDWR);  return 0;}//列举待接收文件int listGFiles(gsNode **list, gsNode *gs, int size){  filenode *curFile;  int tmp=0;  while ((gs!=NULL)&&(tmp<size))  {    if ((gs->transferring==0)&&(gs->cancelled==0))    {      *list++ = gs;      tmp++;    }    gs = gs->next;  }    return tmp;  }///////////////////////////////////////////////////登录int login(){  command com;  initCommand(&com, IPMSG_BR_ENTRY);    com.peer.sin_family = AF_INET;  com.peer.sin_port = htons(IPMSG_DEFAULT_PORT);    if (inet_pton(AF_INET, allHosts, &com.peer.sin_addr)<0)    printf("login: Ip error.\n");    strncpy(com.additional, pwd->pw_name, MSGLEN);    sendMsg(&com);  }//退出int logout(){  command com;  initCommand(&com, IPMSG_BR_EXIT);    com.peer.sin_family = AF_INET;  com.peer.sin_port = htons(IPMSG_DEFAULT_PORT);    if (inet_pton(AF_INET, allHosts, &com.peer.sin_addr)<0)    printf("logout: error\n");  strncpy(com.additional, pwd->pw_name, MSGLEN);    sendMsg(&com);  printf("Bye!\n");  }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -