zoukankan      html  css  js  c++  java
  • Linux C/S文件传输和云端文件下载服务模拟

    /*
     * 这是模拟云端和本地pc的音乐文件的上位机同步程序。
     * xiaoyang @2011.3
     * For PIC32单片机大赛
     *
     * 本程序完全开源,无版权限制。可任意修改使用。
     */
     
    +--------------+
    | 实现说明	|
    +--------------+ 
    本模拟程序采用linux Socket和Qt界面开发而成,以实现云端和本地,本地和CloudPlayer之间的数据传输。由于云端环境搭建困难,采用模拟的方式实现相应的效果。
    相关技术:linux socket、多线程、文件管理,qt界面编程
    
    +-----------+
    | client端 |
    +-----------+
    使用方法:
    双击打开Client即可
    
    功能说明:
    --------
    client-0.8文件夹中放置的是本地pc服务程序。它的基本功能包括:
    (1).获取“云端”音乐文件列表.
    (2).下载”云端“选定的音乐文件.
    (3).本地pc音乐文件管理.
    (4).向CloudPlayer发送音乐文件.
    
    开发环境说明:
    OS:		Ubuntu 10.04
    界面:	Qt GUI
    IDE:	Qt4.6 Creator
    其他;	不支持跨平台运行
    
    +-------------------------------------+
    | server端(模拟云端)	|
    +-------------------------------------+
    使用方法:
    在终端进入路径,如下运行:
    $: chmod 777 server
    $: ./server
    
    功能说明:
    --------
    client-0.8文件夹中放置的是本地pc服务程序。它的基本功能包括:
    (1).监听本地请求事件.
    (2).将“云端”音乐文件列表传送到本地.
    (3).将“云端”选定的音乐文件下载到本地.
    
    开发环境说明:
    OS:		Ubuntu 10.04
    界面:	linux命令行界面
    IDE:	无
    其他;	不支持跨平台运行
    

    现把服务端代码粘上来:

    /*
     * file trans server
     *
     * xiaoyang 2011.3.20
     */
    #include <netinet/in.h>    // for sockaddr_in
    #include <sys/types.h>    // for socket
    #include <sys/socket.h>    // for socket
    #include <stdio.h>        // for printf
    #include <stdlib.h>        // for exit
    #include <string.h>        // for bzero
    #include <sys/types.h>
    #include <dirent.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <ctime>
    
    #include <string>
    #include <vector>
    #include <iostream>
    
    using namespace std;
    /*
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    */
    #define SERVER_PORT 			9800 
    #define LENGTH_OF_LISTEN_QUEUE  20
    #define BUFFER_SIZE 			1024
    #define FILE_NAME_MAX_SIZE 		512
    #define MAX_INFO				1024
    
    #define CMD_LIST    "list"
    #define CMD_DOWN    "download"
    #define CMD_STOP    "stop"
    
    #define RETURN_OK	"ok"
    
    #define MUSIC_PATH	"./Music"
    
    #pragma pack (1)
    typedef struct FILE_INFO{
        char name[512];
        unsigned long size;
        time_t mtime;    //last modified time
    }FileInfo;
    #pragma pack()
    /*
     * by xiaoyang @2011.3.20
     * function:file scan under given directionary
     * path:    the given dir
     * strvec:  Vector to load scan result(warnning:itsval will be changed!)
     * return:  0 if success,or -1 if failed
     */
    
    /*
     * read lenghth of a file
     * return 0 if can't find file, or 1
     */
    int
    get_file_info ( vector <string> strvec,vector<FileInfo> &file_info)
    {
      struct stat buf;
    
      for (vector < string >::iterator iter = strvec.begin ();
           iter != strvec.end (); ++iter)
      {
          if (stat ((*iter).c_str(), &buf) < 0)
            {
              continue;
            }
    
           FileInfo new_info;
           strcpy(new_info.name ,(*iter).c_str());
           new_info.size = (unsigned long) buf.st_size;
           new_info.mtime = buf.st_mtime;
           file_info.push_back(new_info);
      }
    
      return 1;
    }
    
    
    /*
     * read lenghth of a file
     * return 0 if can't find file, or its lenghth
     */
    unsigned long
    get_file_size (const char *filename)
    {
      struct stat buf;
      if (stat (filename, &buf) < 0)
        {
          return 0;
        }
      return (unsigned long) buf.st_size;
    }
    
    
    /*
     * check if a path is a dir
     * return 0 if is dir or -1 for others
     */
    int if_dir(char *path)
    {
        struct stat st;
        stat(path,&st);
        if (S_ISDIR(st.st_mode))
        {
            printf("is a dir\n");
            return 0;
        }else
        {
            printf("is not a dir\n");
            return -1;
        }
        return -1;
    }
    
    /*
     * function:file scan under given directionary
     * path:    the given dir
     * strvec:  Vector to load scan result(warnning:itsval will be changed!)
     * return:  0 if success,or -1 if failed
     */
    
    int
    scan_allfile (const char *path, vector <string> &strvec)
    {
      DIR *dp;			//dir stream
      struct dirent *entry;		//dir infomation
      //struct stat statbuf;
    
      //open dir,test if it exist
      if ((dp = opendir (path)) == 0)
        {
          fprintf (stderr, "open dir failed\n");
          return -1;
        }
    
      //read dir
      while ((entry = readdir (dp)) != 0)
        {
          //ignore .. dir
          if (!strcmp (entry->d_name, ".") || !strcmp (entry->d_name, ".."))
    	{
    	  continue;
    	}
    
          //get file info and add it into strvec
          string tmp_path (path);
          if (*(tmp_path.end () - 1) != '/')
    	tmp_path += '/';
          tmp_path += entry->d_name;
    
    
          //if dir
          if (entry->d_type == 4)
    	{
    	  scan_allfile (tmp_path.c_str (), strvec);
    	}
          else
            {
              strvec.push_back (tmp_path);
    	  //do nothing
    	}
        }
      closedir (dp);
      return 0;
    }
    
    /*
     *
     * test function
     */
    int
    test_main ()
    {
      char *path = (char*)MUSIC_PATH;
      vector < string > strvec;
      vector<FileInfo> fi;
      scan_allfile (path, strvec);
      get_file_info (  strvec,fi);
      for (vector < FileInfo >::iterator iter = fi.begin ();
         iter != fi.end (); ++iter)
      {
          cout << (*iter).name << "\t\t";
          cout << (*iter).size << "\t\t";
          cout << ctime( &(*iter).mtime) << endl;
      }
    
      return 0;
    }
    
    
    int main(int argc, char **argv)
    {
    	char cmd[512]={'\0'};
    	int server_socket = -1;
    	char buffer[BUFFER_SIZE] = {0};
        //设置一个socket地址结构server_addr,代表服务器internet地址, 端口
        struct sockaddr_in server_addr;
        
        bzero(&server_addr,sizeof(server_addr)); //把一段内存区的内容全部设置为0
        server_addr.sin_family = AF_INET;
        server_addr.sin_addr.s_addr = htons(INADDR_ANY);
        server_addr.sin_port = htons(SERVER_PORT);
    
        //创建用于internet的流协议(TCP)socket,用server_socket代表服务器socket
        server_socket = socket(PF_INET,SOCK_STREAM,0);
        if( server_socket < 0)
        {
            printf("Create Socket Failed!");
            exit(1);
        }
        
        //把socket和socket地址结构联系起来
        if( bind(server_socket,(struct sockaddr*)&server_addr,sizeof(server_addr)))
        {
            printf("Server Bind Port : %d Failed!", SERVER_PORT); 
            exit(1);
        }
        
        //server_socket用于监听
        if ( listen(server_socket, LENGTH_OF_LISTEN_QUEUE) )
        {
            printf("Server Listen Failed!"); 
            exit(1);
        }
        
        while (1) //服务器端要一直运行
        {
            //定义客户端的socket地址结构client_addr
            struct sockaddr_in client_addr;
            socklen_t length = sizeof(client_addr);
    
            //接受一个到server_socket代表的socket的一个连接
            //如果没有连接请求,就等待到有连接请求--这是accept函数的特性
            //accept函数返回一个新的socket,这个socket(new_server_socket)用于同连接到的客户的通信
            //new_server_socket代表了服务器和客户端之间的一个通信通道
            //accept函数把连接到的客户端信息填写到客户端的socket地址结构client_addr中
            printf("server[%d]:wait for client..\n",server_socket);
            int new_server_socket = accept(server_socket,(struct sockaddr*)&client_addr,&length);
            if ( new_server_socket < 0)
            {
                printf("Server Accept Failed!\n");
                break;
            }
            
    		printf("server already setup..\n");
            bzero(buffer, BUFFER_SIZE);
            length = recv(new_server_socket,buffer,BUFFER_SIZE,0);//这里先接收客户端发来的命令
            if (length < 0)
            {
                printf("Cmd invalid\n");
                break;
            }
            buffer[length+1]='\0';
            //
            printf("get command:%s\n",buffer);
            
            if(strcmp(buffer,CMD_DOWN) == 0){
            	bzero(buffer, BUFFER_SIZE);
    			
    			//return ok
    			strcpy(buffer,(char*)RETURN_OK);
    			if(send(new_server_socket,buffer,64,0)<0)
                {
                    printf("Send size Failed\n");
                    break;
                }
                bzero(buffer, BUFFER_SIZE);
    			printf("send ok,ready for download\n");
    			
    			//get filename
            	length = recv(new_server_socket,buffer,BUFFER_SIZE,0);//这里先接收客户端发来的要获取的文件名
    		    if (length < 0)
    		    {
    		        printf("Server Recieve Data Failed!\n");
    		        break;
    		    }
    			buffer[length+1]='\0';
    			printf("get filename:%s\n",buffer);
    
    		    char file_name[FILE_NAME_MAX_SIZE+1];
    		    bzero(file_name, FILE_NAME_MAX_SIZE+1);
    		    strncpy(file_name, buffer, strlen(buffer)>FILE_NAME_MAX_SIZE?FILE_NAME_MAX_SIZE:strlen(buffer));
    		    FILE * fp = fopen(file_name,"r");
    		    if(NULL == fp )
    		    {
    		        printf("File:\t%s Not Found\n", file_name);
    		    }
    		    else
    		    {
    		        bzero(buffer, BUFFER_SIZE);
    		        int file_block_length = 0;
    		        while( (file_block_length = fread(buffer,sizeof(char),BUFFER_SIZE,fp))>0)
    		        {
    		            //printf("file_block_length = %d\n",file_block_length);
    		            //发送buffer中的字符串到new_server_socket,实际是给客户端
    		            if(send(new_server_socket,buffer,file_block_length,0)<0)
    		            {
    		                printf("Send File:\t%s Failed\n", file_name);
    		                break;
    		            }
    		            bzero(buffer, BUFFER_SIZE);
    		        } 
    				//这段代码是循环读取文件的一段数据,在循环调用send,发送到客户端,
    				//这里强调一点的TCP每次接受最多是1024字节,多了就会分片,因此每次发送时尽量不要超过1024字节。
    		        fclose(fp);
    		        printf("File:\t%s Transfer Finished\n",file_name);
    		    }
            	goto end_session;
            }else if(strcmp(buffer,CMD_LIST) == 0){
            	bzero(buffer, BUFFER_SIZE);
    		    
    		    //wait for ok
    		    length = recv(new_server_socket,buffer,BUFFER_SIZE,0);//recv ok
    		    if (length < 0)
    		    {
    		        printf("Cmd invalid\n");
    		        break;
    		    }
    		    buffer[length+1]='\0';
    		    printf("get message1:%s\n",buffer);
            	if(strcmp(buffer,RETURN_OK) != 0){
            		printf("unknow echo\n");
            		goto end_session;
            	}
            	//send file count
    			char *path = (char*)MUSIC_PATH;
    			vector < string > strvec;
    			vector<FileInfo> fi;
    			scan_allfile (path, strvec);
    			get_file_info (  strvec,fi);
    			
    			sprintf(buffer,"%d",fi.size());
    			if(send(new_server_socket,buffer,64,0)<0)
                {
                    printf("Send size Failed\n");
                    break;
                }
                bzero(buffer, BUFFER_SIZE);
    			printf("send count of file info ok\n");
    			
    			//send data
    			char* temp_buffer = (char*)malloc(sizeof(FileInfo)*MAX_INFO);
    			bzero(temp_buffer, sizeof(FileInfo)*MAX_INFO);
    			unsigned int i = 0;
    			for (vector < FileInfo >::iterator iter = fi.begin();
    			 	iter != fi.end ();
    			 	++iter)
    			{
    				char* pos = temp_buffer + i * sizeof(FileInfo);
    				memcpy(pos,&(*iter),sizeof(FileInfo));
    			  	i++;
    			}
    			//调试代码
    			i = 0;
    			for (vector < FileInfo >::iterator iter = fi.begin ();
    			 	iter != fi.end ();
    			 	++iter)
    			{
    				FileInfo *temp_info =(FileInfo *)(temp_buffer + i * sizeof(FileInfo));
    				printf("\t\tfile:%s\n",temp_info->name);
    			  	i++;
    			}
    			
    			//wait for ok
    			bzero(buffer, BUFFER_SIZE);
    		    length = recv(new_server_socket,buffer,BUFFER_SIZE,0);//recv ok
    		    if (length < 0)
    		    {
    		        printf("Cmd invalid\n");
    		        break;
    		    }
    		    buffer[length+1]='\0';
    		    printf("get message2:%s\n",buffer);
            	if(strcmp(buffer,RETURN_OK) != 0){
            		printf("unknow echo\n");
            		goto end_session;
            	}
            	
            	//send data
    			if(send(new_server_socket,temp_buffer,fi.size()*sizeof(FileInfo),0)<0)
    	        {
    	            printf("Send file info Failed\n");
    	        }
    			free(temp_buffer);
            	bzero(buffer, BUFFER_SIZE);
            	printf("file info send ok!\n");
            	
            	fi.clear();
            	strvec.clear();
            	goto end_session;
            }else if(strcmp(buffer,CMD_STOP) == 0){
            	bzero(buffer, BUFFER_SIZE);
            	goto end_session;
            }else{
            
            }
    end_session:
    
            //关闭与客户端的连接
            close(new_server_socket);
        }
    end:
        //关闭监听用的socket
        close(server_socket);
        return 0;
    }
    

    上图:

    next:

    next:

  • 相关阅读:
    最舒适的路线(并查集)
    POJ 2411 状态压缩DP
    NYOJ 708 ones
    HUD 1024 Max Sum Plus Plus
    最长上升子序列
    HDU 4717 The Moving Points
    重新开始写随笔
    读书的意义
    读《如何阅读一本书》笔记
    读《GRAY HAT PYTHON》笔记
  • 原文地址:https://www.cnblogs.com/yixiaoyang/p/1990915.html
Copyright © 2011-2022 走看看