📄 send_receive.c
字号:
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 + -