void *thread_function(void) { fd_set m_fdset; //待检查文件的描述符 struct timeval timeout = {1, 0}; //设置超时时间为1秒 //用select超时实现非阻塞读取标准输入 while(1) { //select函数不会修改timeout的值,所以每次循环都应该重新赋值 timeout.tv_sec = 1; timeout.tv_usec = 0; if(FILE_STATE_START == m_filestate) { FD_ZERO(&m_fdset); //清空m_fdset变量 FD_SET(STDIN_FILENO, &m_fdset);//设置为标准输入 switch(select(STDIN_FILENO+1, &m_fdset, NULL, NULL, &timeout)) { //出错 case -1: perror("select"); break; //超时 case 0: break; //发生状态变化的文件描述符的个数 default: if(FD_ISSET(STDIN_FILENO, &m_fdset)) { char ch = fgetc(stdin); //文件传输暂停 if(FILE_TRANS_PAUSE == atoi(&ch)) { m_filestate = FILE_STATE_PAUSE; } //文件传输停止 else if(FILE_TRANS_STOP == atoi(&ch)) { m_filestate = FILE_STATE_STOP; } } break; } } else { //没有传输文件,线程休眠 sleep(1); } } }
2、主函数
int main(int argc, char *argv[]) { int sockfd = -1; int sockerr = 0; int socklen = sizeof(struct sockaddr_in); struct sockaddr_in server_addr; //文件传输相关 int retval = 0; //文件传输返回字节数 int torecv = 0; //剩余要接收的文件大小 char buf[BUFFER_SIZE] = {0}; FILE *fp = NULL; protocol m_protocol; //协议结构体 server_config m_config; //服务器配置结构体 file_info m_fileinfo; //传输文件信息结构体 memset(&m_fileinfo, 0, sizeof(file_info)); pthread_t thread_handle = 0; //线程句柄 //创建一个线程在文件传输时接收标准输入 if(pthread_create(&thread_handle, NULL, (void*)thread_function, NULL) != 0) { perror("pthread_create"); return -1; } //创建一个套接字 sockfd = socket(AF_INET, SOCK_STREAM, 0); if(sockfd == -1) { perror("socket"); return -1; } //配置服务器地址与端口 bzero(&server_addr, sizeof(struct sockaddr_in)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(SOCKET_PORT); server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //连接服务器 if(connect(sockfd, (struct sockaddr*)&server_addr, socklen) == -1) { perror("connect"); close(sockfd); return -1; } while(!sockerr) { char ch[100] = {0}; memset(&m_protocol, 0, sizeof(protocol)); printf("***********************n" "1:Get file list *n" "2:Get server config *n" "3:Set server config *n" "4:Start file trans *n" "5:Start file trans *n" "6:Start file trans *n" "***********************n"); printf("Please input command:"); scanf("%s", ch); m_protocol.cmd = ch[0] - '0'; //对异常输入进行判断 if(m_protocol.cmd < 1 || m_protocol.cmd > 6 || ch[1] != 0) { printf("The command is invalid!n"); } else { switch(m_protocol.cmd) { //获取文件列表 case GET_FILE_LIST: if(-1 == write(sockfd, (char*)&m_protocol, sizeof(protocol))) { perror("write"); sockerr = 1; } memset(buf, 0, BUFFER_SIZE); //当socket链接中断时会返回0,read错误时返回-1 if(read(sockfd, buf, BUFFER_SIZE) <= 0) { perror("read"); sockerr = 1; break; } else { printf("%s", buf); } break; //获取服务器配置参数 case GET_SER_CONFIG: if(-1 == write(sockfd, (char*)&m_protocol, sizeof(protocol))) { perror("write"); sockerr = 1; } memset(&m_config, 0, sizeof(server_config)); //当socket链接中断时会返回0,read错误时返回-1 if(read(sockfd, (char*)&m_config, sizeof(server_config)) <= 0) { perror("read"); sockerr = 1; break; } else { printf("name:%sclient_max:%dn", m_config.name, m_config.clieng_max); } break; //设置服务器配置参数 case SET_SER_CONFIG: printf("Please input server name:"); scanf("%s", m_protocol.name); printf("Please input the max number of server:"); scanf("%d", &m_protocol.length); if(-1 == write(sockfd, (char*)&m_protocol, sizeof(protocol))) { perror("write"); sockerr = 1; } //获取服务器配置的结果 if(read(sockfd, (char*)&m_config, sizeof(server_config)) <= 0) { perror("read"); sockerr = 1; } else { if(!xtrcmp(m_protocol.name, "") { printf("Set server config failed!"); } else { printf("Set server config success!n"); printf("name:%snclient_max:%dn", m_config.name, m_config.client_max); } } break; //文件开始传输 case FILE_TRANS_START: if(torecv > 0) { strncpy(m_protocol.name, m_fileinfo.name, NAME_LEN); printf("FILE name:%sn", m_protocol.name); } else { printf("Please input file name:"); scanf("%s", m_protocol.name); } if(-1 == write(sockfd, (char*)&m_protocol, sizeof(protocol))) { perror("write"); sockerr = 1; } //接收服务器的回复,判断是否满足文件传输的条件 memset(&m_protocol, 0, sizeof(protocol)); if(read(sockfd, (char*)&m_protocol, sizeof(protocol)) <= 0) { perror("read"); sockerr = 1; } else { if(strcmp(m_protocol.name, "") != 0) { if(torecv > 0) { //继续传输旧文件,以附加的方式打开只写文件 fp = fopen(m_protocol.name, "a") } else { //传输新文件 torecv = m_protocol.length; fp = fopen(m_protocol.name, "w"); } if(NILL == fp) { perror("fopen"); } else { printf("Start receiving file!n"); m_filestate = FILE_STATE_START; while((retval = read(sockfd, buf, sizeof(buf))) > 0) { fwrite(buf, 1, retval, fp); memset(buf, 0, sizeof(buf)); //计算剩余字节数 torecv -= retval; if(torecv <= 0) { printf("FILE:%s receive success!n", m_protocol.name); //清除文件信息 torecv = 0; memset(&m_fileinfo, 0, sizeof(file_info)); m_filestate = FILE_STATE_STOP; if(write(sockfd, (char*)&m_protocol, sizeof(protocol)) < 0) { perror("write"); sockerr = 1; } break; else { //暂停传输 if(FILE_STATE_PAUSE == filestate) { strncpy(m_fileinfo.name, m_protocol.name, NAME_LEN); printf("FILE_TRANS_PAUSE!n" "Left:%dn", torecv); //发送暂停命令 memset(&M-protocol, 0, sizeof(protocol)); m_protocol.cmd = FILE_TRANS_PAUSE; if(write(sockfd, (char*)&m_protocol, sizeof(protocol)) < 0) { perror("write"); sockerr = 1; } break; } //停止传输 else if(FILE_STATE_STOP == m_filestate) { torecv = 0; memset(&m_fileinfo, 0, sizeof(file_info)); printf("FILE_TRANS_STOP!n"); //发送停止命令 m_protocol.cmd = FILE_TRANS_STOP; if(write(sockfd, (char*)&m_protocol, sizeof(protocol)) < 0) { perror("write"); sockerr = 1; } break; } else { if(write(sockfd, (char*)&m_protocol, sizeof(protocol)) < 0) { perror("write"); sockerr = 1; } } } } fclose(fp); fp = NULL; } } else { printf("File not exist!n"); } } break; //文件暂停传输 case FILE_TRANS_PAUSE: //指令在线程中读取 if(m_filestate != FILE_STATE_START) { printf("No file is transferring!n"); } break; //文件停止传输 case FILE_TRANS_STOP: //指令在线程中读取 if(m_filestate != FILE_STATE_START) { printf("No fole is transferring!n"); } break; default: break; } } } close(sockfd); return 0; }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)