关于linux中网络发送文件程序的问题

seakia 2011-11-01 11:21:17
我只有C语言的基础,什么操作系统,线程,网络编程什么的基础一点没有,在查阅了资料之后写了server和client的程序,但是不能写进文件。之前没有循环发送,但是可以正常传送小文件,为了传送大文件,在while(1)里面写了一个判断文件是否发送完毕的循环发送,但是client端一直写不进文件,一直是0字节。
新手一枚,拍砖轻点。
server端的程序如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<unistd.h>
#include<netdb.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<sys/types.h>
#include<arpa/inet.h>

#define MAXDATASIZE 1024

int main(int argc,char *argv[])
{
int listen_fd,send_fd;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int portnumber,sin_size;
FILE *fp;
int fplen,filelength,sum_data;
char buffer[MAXDATASIZE];
if(argc!=3)
{
fprintf(stderr,"usage:%s portnumber\n",argv[0]);
exit(1);
}
if((fp=fopen(argv[1],"rb"))==NULL)
{
fprintf(stderr,"open file error!\n");
exit(1);
}
if((portnumber=atoi(argv[2]))<0)
{
fprintf(stderr,"usage:%s portnumber\n",argv[0]);
exit(1);
}
if((listen_fd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
fprintf(stderr,"socket error:%s\n",strerror(errno));
exit(1);
}
memset(&server_addr,0,sizeof(struct sockaddr_in));
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(portnumber);
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
if(bind(listen_fd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
{
fprintf(stderr,"bind error:%s\n",strerror(errno));
exit(1);
}
if(listen(listen_fd,10)==-1)
{
fprintf(stderr,"listen error:%s\n",strerror(errno));
exit(1);
}
fseek(fp,0,SEEK_END);
filelength=1024*ftell(fp);
while(1)
{
sin_size=sizeof(client_addr);
if((send_fd=accept(listen_fd,(struct sockaddr *)(&client_addr),&sin_size))==-1)
{
fprintf(stderr,"accept error:%s\n",strerror(errno));
exit(1);
}
fprintf(stdout,"server get connection from %s",inet_ntoa(client_addr.sin_addr));
sum_data=fread(buffer,1,MAXDATASIZE,fp); //每次读进一字节,读取次数为fplen次,则初始发送数据量为fread的返回值
while(sum_data<=filelength)
{
fplen=fread(buffer,1,MAXDATASIZE,fp); //由于每次读入一字节,所以,fplen大小等于每次发送的字节数
write(send_fd,buffer,fplen);
sum_data+=fplen;
}
close(send_fd);
}
close(listen_fd);
exit(0);
}

client端程序如下:


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
#include<arpa/inet.h>

#define MAXDATASIZE 1024

int main(int argc,char *argv[])
{
int client_fd;
int buffer[MAXDATASIZE];
int nbytes,portnumber;
struct sockaddr_in server_addr;
struct hostent *host;
FILE *fp;
if(argc!=4)
{
fprintf(stderr,"usage:%s portnumber\n",argv[0]);
exit(1);
}
if((portnumber=atoi(argv[3]))<0)
{
fprintf(stderr,"usage:%s portnumber\n",argv[0]);
exit(1);
}
if((fp=fopen(argv[2],"wab"))==NULL)
{
fprintf(stderr,"open file error!\n");
exit(1);
}
if((host=gethostbyname(argv[1]))==NULL)
{
fprintf(stderr,"get host error:%s\n",strerror(errno));
exit(1);
}
if((client_fd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
fprintf(stderr,"socket error:%s\n",strerror(errno));
exit(1);
}
memset(&server_addr,0,sizeof(struct sockaddr_in));
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(portnumber);
server_addr.sin_addr=*((struct in_addr *)host->h_addr);
if(connect(client_fd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
{
fprintf(stderr,"connect error:%s\n",strerror(errno));
exit(1);
}
nbytes=read(client_fd,buffer,sizeof(buffer));
fwrite(buffer,1,nbytes,fp); //这里需要写循环么?
printf("Get information %s from %s\n",buffer,inet_ntoa(server_addr.sin_addr));
close(client_fd);
fclose(fp);
return 0;
}
...全文
78 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq120848369 2011-11-04
  • 打赏
  • 举报
回复
给你贴个简单示例:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>

#define SRV_HOST "127.0.0.1"
#define SRV_PORT 13000
#define FILE_PATH "./sendfile.txt"

int main()
{
int clifd;

if( (clifd=socket(AF_INET,SOCK_STREAM,0))==-1 )
{
perror("socket");
return 1;
}

struct sockaddr_in srvAddr;

srvAddr.sin_family=AF_INET;
srvAddr.sin_port=htons(SRV_PORT);
srvAddr.sin_addr.s_addr=inet_addr(SRV_HOST);

if( connect(clifd,(struct sockaddr*)&srvAddr,sizeof(struct sockaddr_in))==-1 )
{
perror("connect");
return 2;
}

int filefd=open(FILE_PATH,O_RDONLY);

if(filefd==-1)
{
perror("open");
return 3;
}

struct stat buf;
int size;

if(fstat(filefd,&buf)==-1)
{
perror("fstat");
return 4;
}

size=buf.st_size;

int on=1;

if(ioctl(clifd,FIONBIO,&on)==-1)
{
perror("ioctl");
return 5;
}

int ret;

while(true)
{
ret=sendfile(clifd,filefd,NULL,5000);

if(ret==-1)
{
perror("sendfile");

if(errno!=EAGAIN)
{
return 6;
}
}
else if(ret==0)
{
printf("sendfile done.......\n");
break;
}
else
{
printf("send %d\n",ret);
//size-=ret;
}
}

close(clifd);
close(filefd);

return 0;
}


#include "net.h"

#define STORE_PATH "./store.txt"

int main()
{
int srvfd;

if( (srvfd=socket(AF_INET,SOCK_STREAM,0))==-1 )
{
perror("socket");
return 1;
}

struct sockaddr_in srvAddr;
srvAddr.sin_family=AF_INET;
srvAddr.sin_port=htons(SRV_PORT);
srvAddr.sin_addr.s_addr=inet_addr(SRV_HOST);

int on=1;

if(setsockopt(srvfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(int))==-1)
{
perror("setsockopt");
return 2;
}

if( bind(srvfd,(struct sockaddr*)&srvAddr,sizeof(struct sockaddr_in))==-1 )
{
perror("bind");
return 3;
}

if( listen(srvfd,5)==-1 )
{
perror("listen");
return 3;
}

char buffer[1000];
int ret,fd;

if( (fd=open(STORE_PATH,O_CREAT|O_TRUNC|O_WRONLY,S_IRUSR|S_IWUSR))==-1 )
{
perror("open");
return 4;
}

struct sockaddr_in cliAddr;
socklen_t len=sizeof(cliAddr);

int clifd=accept(srvfd,(struct sockaddr*)&cliAddr,&len);

if(clifd==-1)
{
perror("accept");
return 5;
}

while(true)
{
ret=recv(clifd,buffer,1000,0);

if(ret==-1)
{
perror("recv");

if(errno!=EAGAIN)
{
return 6;
}
}
else if(ret>0)
{
if(write(fd,buffer,ret)!=ret)
{
perror("write");
return 7;
}
}
else
{
break;
}
}

close(fd);
close(clifd);
close(srvfd);

return 0;
}


JoeBlackzqq 2011-11-04
  • 打赏
  • 举报
回复
楼主的代码哪参考的,感觉有点乱呀! 学习还是得慢慢来,从简单的学起!
seakia 2011-11-03
  • 打赏
  • 举报
回复
client里面循环read不怕把buffer塞满么?
现在我在两个终端中执行client和server程序
两个终端都没有反应
都是一种程序正在执行的状态
这个可能问题是处在哪里了?
[Quote=引用 4 楼 dd_zhouqian 的回复:]

1.server的write函数与client的read函数都要判断返回值是否有效。
2.client的read需要循环接收,client connect server 成功了未必有数据发过来,所以需要循环接收,完了再做下面的写文件处理。
[/Quote]
dd_zhouqian 2011-11-03
  • 打赏
  • 举报
回复
1.server的write函数与client的read函数都要判断返回值是否有效。
2.client的read需要循环接收,client connect server 成功了未必有数据发过来,所以需要循环接收,完了再做下面的写文件处理。
jufeng2309 2011-11-03
  • 打赏
  • 举报
回复
监控下具体write多少字节,这边read多少字节?
还有个问题需要强调,当你程序发送字节数的时候,比如你想发送1024个字节,但系统根据你的网络状态,不一定1024个字节数就能够发出去,所以你需要打印具体发送的字节数和,接收到的字节数。
seakia 2011-11-03
  • 打赏
  • 举报
回复
但是我只发送了一个只有几十字节的小文件
client端就一直写不进去
代码有没有大问题?
[Quote=引用 1 楼 qq120848369 的回复:]

写文件也是需要判断返回值得哦,硬盘负载打的话一样会写不进去。
[/Quote]
qq120848369 2011-11-03
  • 打赏
  • 举报
回复
写文件也是需要判断返回值得哦,硬盘负载打的话一样会写不进去。

23,127

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧