| 发表于:2007-08-08 11:02:44 楼主 |
这是我写的一个c和s交互式文件传输程序,但是它有个问题我无法解决,就是在文件传输的过程中数据流不会断,即使到了文件尾它依然还会继续读数据然后继续发数据,无论c to s,还是s to c,都是如此,我作的文件尾和数据尾判断毫无作用,为什么呢? #include <sys/socket.h> #include <sys/wait.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/time.h> #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <netinet/in.h> #include <sys/stat.h> #include <fcntl.h> #define buffer 1024 int main(int argc, char **argv) { struct sockaddr_in my_addr, other_addr; unsigned int localport, maxlisten; char buf[buffer + 1], filepath[500]; int sockfd, newsock_fd, filenum; file * sendfds, * recvfds, * psock; socklen_t len; fd_set rdfds; struct timeval timeout; int ret, max_fd_num = -1; /*处理参数,将其转换为整数*/ if(argv[1]) localport = atoi(argv[1]); else localport = 8043; if(argv[2]) maxlisten = atoi(argv[2]); else maxlisten = 2; /*开始建立socket*/ if((sockfd = socket(pf_inet, sock_stream, 0)) == -1) { perror( "socket "); exit(1); } bzero(&my_addr, sizeof(my_addr)); my_addr.sin_family = pf_inet; my_addr.sin_port = htons(localport); if(argv[3]) my_addr.sin_addr.s_addr = inet_addr(argv[3]); else my_addr.sin_addr.s_addr = inaddr_any; if(bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -1) { perror( "bind "); exit(1); } if(listen(sockfd, maxlisten) == -1) { perror( "listen "); exit(1); } while(1) { printf( "----监听开始,等待文件传输----\n "); len = sizeof(struct sockaddr); if((newsock_fd = accept(sockfd, (struct sockaddr *) &other_addr, &len)) == -1) { perror( "accept "); exit(1); } else { printf( "接收到了从%s 端口%d 来的连接\n ",inet_ntoa(other_addr.sin_addr),ntohs(other_addr.sin_port)); } printf( "你可以输入你要传输给对方的文件名,注意要指明绝对路径,然后按回车键发送!\n "); while(1) { fd_zero(&rdfds); fd_set(0, &rdfds); max_fd_num = 0; fd_set(newsock_fd, &rdfds); if(newsock_fd > max_fd_num) max_fd_num = newsock_fd; timeout.tv_sec = 1; timeout.tv_usec = 500; ret = select(max_fd_num + 1, &rdfds, null, null,&timeout); if(ret == -1) { perror( "select "); break; } else if(ret == 0) { continue; } else { /*发送文件*/ if(fd_isset(0, &rdfds)) { bzero(buf, buffer + 1); memset (filepath, '\0 ', 501); scanf( "%s ",filepath); if((sendfds = fopen(filepath, "r+ " )) == null) { perror( "open "); break; } filenum = fileno(sendfds); /*将文件指针转换为句柄*/ //psock = fdopen(newsock_fd, 0);/*将文件句柄转换为指针*/ if(!strncasecmp(buf, "quit ", 4)) { printf( "quit the filesend\n "); break; } while(1) { if(feof(sendfds) != 0) { fclose(sendfds); break; } if(read(filenum, buf, buffer) == -1) { perror( "read "); break; } if((len = send(newsock_fd, buf, strlen(buf)-1, 0)) == -1) { perror( "send "); break; } } //fflush(psock); printf( "文件传输完毕! "); } /*接收文件*/ if(fd_isset(newsock_fd, &rdfds)) { bzero(buf, buffer+1); len = recv(newsock_fd, buf, buffer, 0); printf( "控制机有文件需要传给你,请输入文件保存路径,注意如果您的路径中已经包含相同的文件名,此操作将会覆盖原来的文件。\n "); bzero(buf, buffer + 1); memset (filepath, '\0 ', 501); scanf( "%s ",filepath); if((recvfds = fopen(filepath, "w+ " )) == null) { perror( "open "); break; } filenum = fileno(recvfds); if(!strncasecmp(buf, "quit ", 4)) { printf( "quit the filesend\n "); break; } while(fd_isset(newsock_fd, &rdfds)) { if((len = recv(newsock_fd, buf, buffer, 0)) < 0) { perror( "recv "); break; } if(write(filenum, buf, buffer) == -1) { perror( "write "); break; } else if(write(filenum, buf, buffer) == eagain) /*eagain返回表示没有数据可以读*/ { fclose(recvfds); printf( "文件传输完毕! "); break; } } } } } printf( "还想继续传输文件吗?输入no退出,否则继续! "); fflush(stdout); bzero(buf, buffer + 1); scanf( "%s ",filepath); if (!strncasecmp(buf, "no ", 2)) { printf( "结束传输!\n "); break; } } close(sockfd); return 0; } 以上是server端的代码。 |
|
|
|
|