您的位置:程序门 -> linux/unix社区 -> 程序开发区



linux文件传输程序的问题


[收藏此页] [打印本页]选择字色:背景色:字体:[][][]


linux文件传输程序的问题[无满意答案结贴,结贴人:yxyhack]
发表于: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端的代码。

发表于:2007-08-08 11:03:011楼 得分:0
下面是client端的代码。
#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   srvaddr;
unsigned   int   maxlisten;
char   buf[buffer   +   1],   filepath[500];
int   sockfd,   filenum;
file   *   sendfds,   *   recvfds,   *   psock;
socklen_t   len;
fd_set   rdfds;
struct   timeval   timeout;
int   ret,   max_fd_num   =   -1;
        if   (argc   !=   3)  
{
printf( "args   wrong   that   you   used!you   may   use   like   this:\n\t\t%s   ipaddress   port\n\texample:\t%s   127.0.0.1   80\n ",argv[0],   argv[0]);
exit(0);
        }
if   ((sockfd   =   socket(af_inet,   sock_stream,   0))   <   0)  
{
perror( "socket ");
exit(errno);
        }
bzero(&srvaddr,   sizeof(srvaddr));
        srvaddr.sin_family   =   af_inet;
        srvaddr.sin_port   =   htons(atoi(argv[2]));
        if   (inet_aton(argv[1],   (struct   in_addr   *)   &srvaddr.sin_addr.s_addr)   ==   0)  
{
                perror(argv[1]);
                exit(errno);
        }
if   (connect(sockfd,   (struct   sockaddr   *)   &srvaddr,   sizeof(srvaddr))   !=   0)  
{
                perror( "connect ");
                exit(errno);
        }
printf( "\n建立连接成功,你可以输入要传送的文件名,注意要使用绝对路径\n ");
while(1)
{
fd_zero(&rdfds);
fd_set(0,   &rdfds);
max_fd_num   =   0;
fd_set(sockfd,   &rdfds);
if(sockfd   >   max_fd_num)
max_fd_num   =   sockfd;
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(sockfd,   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(sockfd,   buf,   strlen(buf)-1,   0))   ==   -1)
{
perror( "send ");
break;
}
}
//fflush(psock);
fclose(sendfds);
printf( "文件传输完毕! ");


}
if(fd_isset(sockfd,   &rdfds))
{
bzero(buf,   buffer+1);
len   =   recv(sockfd,   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(sockfd,   &rdfds))
{

if((len   =   recv(sockfd,   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;
}


大家帮忙看一下吧,谢谢
发表于:2007-08-08 13:28:252楼 得分:0
不停的传输的原因是这些  
if(feof(sendfds)   !=   0)
{
                      fclose(sendfds);
                        break;
}
if(read(filenum,   buf,   buffer)   ==   -1)
{
      perror( "read ");
        break;
}
//注意:filenum和sendfds是两个不同的数据结构,其内部的指针也是不同的.
因为你没有用sendfds来读取数据和移动文件指针位置,所有其指针位置永远在文件的开头.

read函数自由在读取出错和于到信号的情况下才返回-1的,在读不到数据时,其返回值为0.
在读到尾部时,再去读,不是出错,只是读不到数据而已.
改成
if(read(filenum,   buf,   buffer) <=0)
就可以了

但是改正后,你的程序还是有问题.不能传输文件.

主要的原因是你的程序没有一套机制来告诉对方要传输文件的大小,是否传输完毕,出错等情况.

比如:
服务端给客户端传输文件,文件很小,发完以后,服务端会继续等待对方给数据或则输入给对方的文件名
但此时客户端还在recv处阻塞着,根本不知道文件已经传完了.

就一个连接端口想做成交互式的文件传输程序很困难,ftp是用的两个连接,一个传指令,一个传输数据才作到的.
发表于:2007-08-09 10:55:433楼 得分:0
关注
发表于:2007-08-09 14:21:304楼 得分:0
mark
发表于:2007-09-21 09:39:405楼 得分:0
没有人帮我回答一下了吗?已经要开始结贴了,在一个端口传输命令和文件理论上是可以做到的,pop3协议就是这样的。

看看大家还有什么好的建议,帖子要过期了。


快速检索

最新资讯
热门点击