本套系统功能简介:服务器登陆后,自动扫描指定目录中的指定文件(本文中指定为MP3文件),打印出服务器中的文件及数目,然后等待客户端的连接,一旦有客户端连接,服务器将扫描出的全部同类型文件发送给客户端,实现文件同步。可应用于广播等应用中。
设计思路:服务器先扫描指定类型的文件,将扫描结果存于链表中。然后建立套接字,等待客户端连接,等有客户端连接后,依次发送文件数目,文件名,文件大小及文件内容给客户端。客户端依次接收。
设计难点在于客户端的文件内容的接收,需要文件大小控制文件内容接收循环的跳出,否则会接收下个文件的内容,造成文件接收混乱。
server 端:
-
#include <sys/types.h>
-
#include <sys/socket.h> // 包含套接字函数库
-
#include <stdio.h>
-
#include <netinet/in.h> // 包含AF_INET相关结构
-
#include <arpa/inet.h> // 包含AF_INET相关操作的函数
-
#include <unistd.h>
-
#include<string.h>
-
#include<stdlib.h>
-
#include<fcntl.h>
-
#include<sys/stat.h>
-
#include<dirent.h>
-
-
#define PORT 9999
-
#define BUFFSIZE 1000
-
-
-
-
#define MAXPATH 32
-
#define LEN sizeof(struct list)
-
-
int count=0; //计量歌曲数
-
double filesize; //文件总大小
-
-
struct list
-
{
-
char pathname[1024];
-
char filename[512];
-
struct list *next;
-
};
-
-
struct list *head,*p1,*p2;
-
-
-
void scan_dir(char *dir,int depth) //定义目录扫描函数
-
{
-
DIR *dp;
-
struct dirent *entry;
-
struct stat statbuff;
-
int l;
-
if(!(dp=opendir(dir)))
-
{
-
//puts(\"can\'t open\");
-
return;
-
}
-
-
chdir(dir); //切换到当前目录中去
-
while((entry=readdir(dp))!=NULL)
-
{
-
lstat(entry->d_name,&statbuff); //获取下一级成员属性
-
if(S_IFDIR&statbuff.st_mode) //判断下一级成员是否是目录
-
{
-
if(strcmp(\".\",entry->d_name)==0||
-
strcmp(\"..\",entry->d_name)==0)
-
continue;
-
-
//printf(\"%*s%s/\\n\",depth,\"\",entry->d_name);
-
scan_dir(entry->d_name,depth+4); //调用自身,扫描下一级
-
-
}
-
-
else
-
{
-
l=strlen(entry->d_name);
-
l-=4;
-
if(strcmp(entry->d_name+l,\".mp3\")==0||
-
strcmp(entry->d_name+l,\".MP3\")==0)
-
{ char path_buff[MAXPATH];
-
getcwd(path_buff, MAXPATH);
-
-
-
p1= malloc(LEN);
-
-
strcpy(p1->pathname,path_buff);
-
strcpy(p1->filename,entry->d_name);
-
-
//printf(\"%s hello %s\",p1->pathname,p1->filename);
-
p1->next=0;
-
count++;
-
-
if(count==1)
-
head=p2=p1;
-
else
-
{ p2->next=p1;
-
//p2=p2->next;
-
p2=p1;
-
//printf(\"hello\");
-
-
}
-
-
-
-
int tem;
-
tem = statbuff.st_size;
-
-
filesize+=tem;
-
-
}
-
-
}
-
-
}
-
-
chdir(\"..\"); //回到上一级目录
-
closedir(dp);
-
-
}
-
-
-
int print()
-
{
-
-
struct list *temp;
-
temp=head;
-
//printf(\"......here1\");
-
if(head!=NULL)
-
do {
-
printf(\"%s %s\\n\",temp->pathname,temp->filename);
-
-
temp=temp->next;
-
}while(temp!=NULL);
-
return ;
-
}
-
-
-
-
-
-
int main()
-
{
-
-
puts(\"正在扫描全盘中...\");
-
scan_dir(\"/home\",0);
-
printf(\"列表输出如下:\\n\");
-
-
print();
-
puts(\"扫描结束\\n\");
-
printf(\"共计%d首歌曲\\n\",count);
-
printf(\"总大小为%3.2gMB\\n\",filesize/1024/1024);
-
-
-
-
-
-
-
/* 以下为socket创建过程 */
-
int server_sockfd,client_sockfd;
-
int server_len,client_len;
-
-
struct sockaddr_in server_sockaddr,client_sockaddr;
-
-
server_sockfd = socket(AF_INET,SOCK_STREAM, 0); // 定义套接字类型
-
-
server_sockaddr.sin_family=AF_INET;
-
server_sockaddr.sin_port=htons(PORT);
-
server_sockaddr.sin_addr.s_addr=INADDR_ANY;
-
-
server_len=sizeof(server_sockaddr);
-
-
//允许重复使用本地地址和套接字绑定
-
int j=1;
-
setsockopt(server_sockfd,SOL_SOCKET,SO_REUSEADDR,&j,sizeof(j));
-
-
//绑定端口
-
if(bind(server_sockfd,(struct sockaddr *)&server_sockaddr,server_len)==-1)
-
{
-
perror(\"bind:\");
-
exit(1);
-
}
-
-
//监听端口
-
if(listen(server_sockfd,5)==-1)
-
{
-
perror(\"listen:\");
-
exit(1);
-
}
-
printf(\"Listening...\\n\");
-
-
pid_t pid;
-
-
client_len=sizeof(client_sockaddr);
-
while(1)
-
{
-
if((client_sockfd=accept(server_sockfd,(struct sockaddr *)&client_sockaddr,&client_len))==-1)
-
{
-
perror(\"accept error:\");
-
exit(1);
-
}
-
-
printf(\"%s连接到服务器\\n\",inet_ntoa(client_sockaddr.sin_addr));
-
-
printf(\"准备发送文件...\\n\");
-
-
pid=fork(); //创建子进程
-
-
if(pid==0) //子进程发送数据
-
{
-
//发送文件数目
-
int countbyte;
-
countbyte=send(client_sockfd,&count,4,0);
-
// printf(\"countbyte=%d\\n\",countbyte);
-
-
-
-
-
-
char fileinfo[100]; //定义文件信息,包括文件路径和文件名
-
memset(fileinfo,0,100);
-
char filename[50];
-
memset(filename,0,50);
-
-
-
-
struct stat statbuff;
-
struct list *temp;
-
temp=head;
-
-
-
-
-
if(head!=NULL)
-
do {
-
// printf(\"%s %s\\n\",temp->pathname,temp->filename);
-
-
char c[2]={\'/\'};
-
strcat(temp->pathname,c);
-
strcat(temp->pathname,temp->filename);
-
-
// printf(\"temp->pathname=%s\\n\",temp->pathname);
-
-
strcpy(fileinfo,temp->pathname);
-
strcpy(filename,temp->filename);
-
-
printf(\"fileinfo=%s\\n\",fileinfo);
-
// printf(\"filename=%s\\n\",filename);
-
-
-
-
-
-
-
/*发送文件名*/
-
int sendbytes=0;
-
sendbytes=send(client_sockfd,filename,50,0);
-
printf(\"sendbytes=%d\\n\",sendbytes);
-
-
//发送文件大小
-
int filesize=0;
-
int sendfsize;
-
lstat(fileinfo,&statbuff);
-
filesize=statbuff.st_size;
-
printf(\"filesize =%d\\n\",filesize);
-
sendfsize=send(client_sockfd,&filesize,4,0);
-
// printf(\"sendfsize=%d\\n\",sendfsize);
-
-
-
-
-
/*发送文件内容*/
-
char buff[BUFFSIZE];
-
memset(buff,0,BUFFSIZE);
-
-
FILE * fp = fopen(fileinfo,\"r\");
-
-
if(NULL == fp )
-
{
-
printf(\"File:Not Found\\n\" );
-
}
-
-
else
-
{
-
int file_block_length = 0;
-
-
while( (file_block_length = fread(buff,sizeof(char),BUFFSIZE,fp))>0)
-
{
-
// printf(\"file_block_length = %d\\n\",file_block_length);
-
-
if(send(client_sockfd,buff,file_block_length,0)<0)
-
{
-
printf(\"Send File Failed:\\n\");
-
break;
-
}
-
-
memset(buff,0,BUFFSIZE);
-
}
-
-
fclose(fp);
-
}
-
-
-
temp=temp->next;
-
}while(temp!=NULL);
-
-
-
-
-
printf(\"文件发送完毕\\n\");
-
}//end of child process
-
-
if(pid>0)
-
{
-
close(client_sockfd);
-
}
-
-
} //end of while(1)
-
-
}
客户端:client.c
-
#include <stdio.h>
-
#include <netinet/in.h>
-
#include <sys/types.h> /* See NOTES */
-
#include <sys/socket.h>
-
#include <dirent.h>
-
#include <string.h>
-
#include <sys/stat.h>
-
#include <unistd.h>
-
#include <netdb.h>
-
#include <stdlib.h>
-
-
#define IP_ADDR "192.168.1.14"
-
-
int main()
-
{
-
unsigned char filename[50];
-
int filesize;
-
unsigned char databuf[1000];
-
int sockfd;
-
struct sockaddr_in serv_addr;
-
-
// struct hostent *host;
-
int i;
-
int lastsize=0;
-
-
// host = gethostbyname("localhost");
-
-
sockfd=socket(AF_INET,SOCK_STREAM,0);
-
-
-
serv_addr.sin_family = AF_INET;
-
serv_addr.sin_port = htons(9999);
-
//serv_addr.sin_addr = *((struct in_addr*)host->h_addr);
-
serv_addr.sin_addr.s_addr = inet_addr(IP_ADDR);
-
bzero(&(serv_addr.sin_zero),8);
-
-
if(connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(struct sockaddr))==-1){
-
perror("connect");
-
exit(1);
-
}
-
-
//接收文件数目
-
int count=0;
-
int countbyte;
-
countbyte=recv(sockfd,&count,4,0);
-
-
printf("文件数目=%d\n",count);
-
-
while(count--)
-
{
-
i=recv(sockfd,filename,sizeof(filename),0); //接收文件名
-
// printf("recv %d bytes\n",i);
-
printf("file name=%s\n",filename);
-
-
i=recv(sockfd,&filesize,sizeof(filesize),0); //接收文件大小
-
// printf("recv %d bytes\n",i);
-
printf("filesize=%d\n",filesize);
-
lastsize=filesize; //文件大小赋给变量
-
-
//接收文件内容
-
FILE *fp = fopen(filename,"w");
-
-
-
-
if(NULL == fp )
-
{
-
printf("File: Can Not Open To Write\n");
-
exit(1);
-
}
-
-
i=0;
-
while(lastsize>0)
-
{
-
printf("lastsize=%d\n",lastsize);
-
if(lastsize>sizeof(databuf))
-
{
-
i=recv(sockfd,databuf,sizeof(databuf),0);
-
printf("接收字节i=%d\n",i);
-
-
int write_length = fwrite(databuf,sizeof(char),i,fp);
-
if (write_length<i)
-
{
-
printf("File:Write Failed\n");
-
break;
-
}
-
-
// if(lastsize<5000) printf("recv %d bytes\n",i);
-
}
-
else
-
{
-
printf("i'll recv %d byte only\n",lastsize);
-
i=recv(sockfd,databuf,lastsize,0);
-
printf("接收字节i=%d\n",i);
-
-
-
int write_length = fwrite(databuf,sizeof(char),i,fp);
-
if (write_length<i)
-
{
-
printf("File:Write Failed\n");
-
break;
-
}
-
-
// printf("*******recv %d bytes\n",i);
-
}
-
-
lastsize=lastsize-i;
-
-
-
}
-
-
fclose(fp);
-
printf("该文件接收完毕\n");
-
}
-
return 0;
-
}
阅读(2675) | 评论(0) | 转发(0) |