linuxC socket 发送和接收文件小例子

LINUX C 基于TCP/IP协议的SOCKET收发文件的小例子。

自已没事正看这方面的东西,感觉要想把网络这块弄明白还真不是件简单的事。

程序写的比较繁琐,代码也不合理,有时间再把程序优化一下,加上断点继传的功能。。

服务器端:

[cpp]  view plain copy
  1. /******** http://blog.csdn.net/robertkun ********/  
  2. /*******  服务器程序  (server.c)     ************/  
  3.   
  4. // linux 下读取大于2GB文件时,需指定  
  5. #define _FILE_OFFSET_BITS 64  
  6.   
  7. #include <stdlib.h>  
  8. #include <stdio.h>  
  9. #include <errno.h>  
  10. #include <string.h>  
  11. #include <unistd.h>  
  12. #include <netdb.h>  
  13. #include <sys/socket.h>  
  14. #include <netinet/in.h>  
  15. #include <sys/types.h>  
  16. #include <arpa/inet.h>  
  17. #include <fcntl.h>  
  18.   
  19. // 定义包的大小为512KB  
  20. #define PACK_SIZE 1024*512  
  21.   
  22. int main(int argc, char *argv[])  
  23. {  
  24.     // 设置输出缓冲  
  25.     setvbuf(stdout, NULL, _IONBF, 0);  
  26.     fflush(stdout);  
  27.   
  28.     int sockfd,new_fd;  
  29.     struct sockaddr_in server_addr;  
  30.     struct sockaddr_in client_addr;  
  31.     int sin_size,portnumber;  
  32.     char hello[]="Hello! Are You Fine?\n";  
  33.   
  34.     if((portnumber=atoi("8080"))<0)  
  35.     {  
  36.         fprintf(stderr,"Usage:%s portnumber\a\n",argv[0]);  
  37.         exit(1);  
  38.     }  
  39.   
  40.     /* 服务器端开始建立socket描述符 */  
  41.     if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) {  
  42.         fprintf(stderr,"Socket error:%s\n\a",strerror(errno));  
  43.         exit(1);  
  44.     }  
  45.   
  46.     /* 服务器端填充 sockaddr结构  */  
  47.     bzero(&server_addr,sizeof(struct sockaddr_in));  
  48.     server_addr.sin_family=AF_INET;  
  49.     server_addr.sin_addr.s_addr=htonl(INADDR_ANY);  
  50.     server_addr.sin_port=htons(portnumber);  
  51.   
  52.     /* 捆绑sockfd描述符  */  
  53.     if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1) {  
  54.         fprintf(stderr,"Bind error:%s\n\a",strerror(errno));  
  55.         exit(1);  
  56.     }  
  57.   
  58.     /* 监听sockfd描述符  */  
  59.     if(listen(sockfd,5)==-1) {  
  60.         fprintf(stderr,"Listen error:%s\n\a",strerror(errno));  
  61.         exit(1);  
  62.     }  
  63.   
  64.     while(1)  
  65.     {  
  66.         fprintf(stderr, "server is listening!\n");  
  67.   
  68.         /* 服务器阻塞,直到客户程序建立连接  */  
  69.         sin_size=sizeof(struct sockaddr_in);  
  70.         if( ( new_fd = accept(sockfd,(struct sockaddr *)(&client_addr),(socklen_t*)&sin_size ) ) == -1) {  
  71.             fprintf(stderr,"Accept error:%s\n\a",strerror(errno));  
  72.             exit(1);  
  73.         }  
  74.   
  75.         fprintf(stderr,"Server get connection from %s\n",  
  76.             inet_ntoa(client_addr.sin_addr));  
  77.         if(write(new_fd,hello,strlen(hello))==-1) {  
  78.             fprintf(stderr,"Write Error:%s\n",strerror(errno));  
  79.             exit(1);  
  80.         }  
  81.   
  82.         long int read_size = 0;  
  83.         unsigned long file_len  = 0;  
  84.         int order_id  = 0;  
  85.         char file_name[128] = {'\0'};  
  86.         char file_info[1024] = {'\0'};  
  87.   
  88.         // 读取指令  
  89.         printf("\n\nWaiting for read file info!\n");  
  90.         int nn = 0;  
  91.         if(nn = read(new_fd, file_info, 1024))   
  92.         {  
  93.             // 指令ID  
  94.             int id_h = (int)file_info[0]<<8;  
  95.             order_id = id_h + (int)file_info[1];  
  96.   
  97.             // 文件长度  
  98.             // 高16位  
  99.             unsigned long len_hig_1 = 0;  
  100.             memcpy(&len_hig_1, &file_info[2], sizeof(file_info[2]));  
  101.   
  102.             unsigned long len_hig_2 = 0;  
  103.             memcpy(&len_hig_2, &file_info[3], sizeof(file_info[3]));  
  104.   
  105.             unsigned long len_hig = len_hig_1 * 256 + len_hig_2;  
  106.   
  107.             // 低16位  
  108.             unsigned long len_low_1 = 0;  
  109.             memcpy(&len_low_1, &file_info[4], sizeof(file_info[4]));  
  110.   
  111.             unsigned long len_low_2 = 0;  
  112.             memcpy(&len_low_2, &file_info[5], sizeof(file_info[5]));  
  113.   
  114.             int len_low = len_low_1 * 256 + len_low_2;  
  115.             file_len = len_hig * 256 * 256 + len_low;  
  116.   
  117.             // 文件名称  
  118.             strncpy(file_name, &file_info[6], strlen(&file_info[6]));  
  119.   
  120.             printf("order = %d, %lu, %s\n", order_id, file_len, file_name);  
  121.   
  122.             if((strlen(file_name) == 0) || (file_len == 0))  
  123.             {  
  124.                 printf("Read file info error!\n File_name or file_len is zero!\n");  
  125.                 close(new_fd);  
  126.                 continue;  
  127.             }  
  128.         }  
  129.         else {  
  130.             printf("Read file info error!\n");  
  131.             close(new_fd);  
  132.             close(sockfd);  
  133.             exit(0);  
  134.         }  
  135.   
  136.         // 写入文件  
  137.         printf("\n\nWaiting for read file content!\n");  
  138.         FILE* pf = fopen(file_name, "wb+");  
  139.         if(pf == NULL)  
  140.         {  
  141.             printf("Open file error!\n");  
  142.             close(new_fd);  
  143.             continue;  
  144.         }  
  145.   
  146.         char buff[PACK_SIZE] = {'\0'};  
  147.         while(read_size <= file_len) {  
  148.             //bzero(buff, 1024);  
  149.             int rlen = read(new_fd, buff, PACK_SIZE);  
  150.             if(rlen) {  
  151.                 //system("clear");  
  152.                 printf("\n\nRead package size = %d\n", rlen);  
  153.   
  154.                 int wn = fwrite(buff, sizeof(char), rlen, pf);  
  155.                 read_size += rlen;  
  156.   
  157.                 printf("write file size = %d\n", wn);  
  158.                 //printf("Read  total  size = %d\n", read_size);  
  159.             }  
  160.             else {  
  161.                 printf("Read over!...%d\n", rlen);  
  162.                 break;  
  163.             }  
  164.         } // End While  
  165.   
  166.         printf("File len = %ld ... Already read size = %ld\n", file_len, read_size);  
  167.       
  168.         /* 这个通讯已经结束     */  
  169.         fclose(pf);  
  170.         close(new_fd);  
  171.         /* 循环下一个     */  
  172.     }  
  173.   
  174.     close(sockfd);  
  175.     exit(0);  
  176. }  


客户端:

[cpp]  view plain copy
  1. /******** http://blog.csdn.net/robertkun ********/  
  2. /******* 客户端程序  client.c        ************/  
  3.   
  4. // linux 下读取大于2GB文件时,需指定  
  5. #define _FILE_OFFSET_BITS 64  
  6.   
  7. #include <stdlib.h>  
  8. #include <stdio.h>  
  9. #include <errno.h>  
  10. #include <string.h>  
  11. #include <unistd.h>  
  12. #include <netdb.h>  
  13. #include <sys/socket.h>  
  14. #include <netinet/in.h>  
  15. #include <sys/types.h>  
  16. #include <arpa/inet.h>  
  17. #include <sys/stat.h>  
  18. #include <fcntl.h>    // 文件读写  
  19.   
  20. // 定义包的大小为512KB  
  21. #define PACK_SIZE 1024*512  
  22.   
  23. char* get_file_name(char* fn);  
  24. unsigned long get_file_size(const char *path);  
  25.   
  26. int main(int argc, char *argv[])  
  27. {  
  28.     if(argc < 2)  
  29.     {  
  30.         printf("please input:<ip> <port> <filePath>.\n");  
  31.         return 0;  
  32.     }  
  33.   
  34.         // 设置输出缓冲  
  35.         setvbuf(stdout, NULL, _IONBF, 0);  
  36.         fflush(stdout);  
  37.   
  38.     char* filePath = argv[3];  
  39.     if(access(filePath, F_OK) != 0)  
  40.     {  
  41.         printf("file not existed!\n");  
  42.         return 0;  
  43.     }  
  44.   
  45.         int sockfd;  
  46.         char buff[1024] = {'\0'};  
  47.         struct sockaddr_in server_addr;  
  48.         struct hostent *host;  
  49.         int portnumber,nbytes;  
  50.   
  51.     const char* ip = argv[1];  
  52.         if((host=gethostbyname(ip))==NULL)  
  53.         {  
  54.                 fprintf(stderr,"Gethostname error\n");  
  55.                 exit(1);  
  56.         }  
  57.   
  58.     const char* port = argv[2];  
  59.         if((portnumber=atoi(port))<0)  
  60.         {  
  61.                 fprintf(stderr,"Usage:%s hostname portnumber\a\n",argv[0]);  
  62.                 exit(1);  
  63.         }  
  64.   
  65.         /* 客户程序开始建立 sockfd描述符  */  
  66.         if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)  
  67.         {  
  68.                 fprintf(stderr,"Socket Error:%s\a\n",strerror(errno));  
  69.                 exit(1);  
  70.         }  
  71.   
  72.         /* 客户程序填充服务端的资料       */  
  73.         bzero(&server_addr,sizeof(server_addr));  
  74.         server_addr.sin_family=AF_INET;  
  75.         server_addr.sin_port=htons(portnumber);  
  76.         server_addr.sin_addr=*((struct in_addr *)host->h_addr);  
  77.   
  78.         /* 客户程序发起连接请求         */  
  79.         if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)  
  80.         {  
  81.                 fprintf(stderr,"Connect Error:%s\a\n",strerror(errno));  
  82.                 exit(1);  
  83.         }  
  84.   
  85.         /* 连接成功了           */  
  86.         if((nbytes=read(sockfd,buff,1024))==-1)  
  87.         {  
  88.                 fprintf(stderr,"Read Error:%s\n",strerror(errno));  
  89.                 exit(1);  
  90.         }  
  91.         buff[nbytes]='\0';  
  92.         printf("I have received:%s\n",buff);  
  93.   
  94.     /******* 发送指令 ********/  
  95.     bzero(buff,1024);  
  96.     // 指令ID  
  97.     int order = 0x0010;  
  98.     int order_h = order >> 8;  
  99.     buff[0] = (char)order_h;  
  100.     buff[1] = (char)order;  
  101.   
  102.     // 文件长度  
  103.     unsigned long len = get_file_size(filePath);  
  104.     printf("file size = %lu\n", len);  
  105.   
  106.     // 高16位  
  107.     int len_h = len >> 16;  
  108.     int len_h_1 = len_h >> 8;  
  109.     buff[2] = (char)len_h_1;  
  110.     buff[3] = (char)len_h;  
  111.   
  112.     // 低16位  
  113.     int len_l = len;  
  114.     int len_l_1 = len_l >> 8;  
  115.     buff[4] = (char)len_l_1;  
  116.     buff[5] = (char)len_l;  
  117.   
  118.     // 文件名称  
  119.     char* fileName = get_file_name(filePath);  
  120.     printf("file name = %s\n", fileName);  
  121.     strncpy(&buff[6], fileName, strlen(fileName));  
  122.   
  123.     write(sockfd,buff,1024);      
  124.       
  125.     /******* 发送文件 ********/  
  126.     printf("file path = %s\n", filePath);  
  127.     FILE* pf = fopen(filePath, "rb");  
  128.     if(pf == NULL) {  
  129.         printf("open file failed!\n");  
  130.         exit(0);  
  131.     }  
  132.   
  133.     char pack[PACK_SIZE] = {'\0'};  
  134.     while((len = fread(pack, sizeof(char), PACK_SIZE, pf)) > 0)  
  135.         {  
  136.         system("clear");  
  137.         printf("send data size = %d \t", len);  
  138.         write(sockfd, pack, len);  
  139.         bzero(pack,PACK_SIZE);  
  140.         //sleep(1);  
  141.         }  
  142.       
  143.         /* 结束通讯     */  
  144.         close(sockfd);  
  145.         exit(0);  
  146. }  
  147.   
  148. char* get_file_name(char* fn)  
  149. {  
  150.     int last = 0;  
  151.     char* pfn = fn+strlen(fn)-1;  
  152.     int i=0;  
  153.     for(i=0; i<strlen(fn); ++i)  
  154.     {  
  155.         if(*pfn-- == '/')  
  156.         {  
  157.             last = strlen(fn)-i;  
  158.             break;  
  159.         }  
  160.     }  
  161.   
  162.     char* name = (char*)malloc(sizeof(char)*256);  
  163.     char* pname = name;  
  164.     int j=0;  
  165.     for(j=last; j<strlen(fn); ++j, ++pname)  
  166.     {  
  167.         *pname = fn[j];  
  168.     }  
  169.       
  170.     return name;  
  171. }  
  172.   
  173. unsigned long get_file_size(const char *path)  
  174. {  
  175.     unsigned int filesize = 0;  
  176.     struct stat statbuff;  
  177.     if(stat(path, &statbuff) < 0) {  
  178.         printf("Get file stat failed!\n");  
  179.         return filesize;  
  180.     }else{  
  181.         filesize = statbuff.st_size;  
  182.     }  
  183.   
  184.     return filesize;  
  185. }  

MAKEFILE:

服务器端:

[cpp]  view plain copy
  1. object=server.o  
  2.   
  3. server.o:  
  4.         gcc -g -c server.c  
  5.         gcc -o server $(object)  
  6.   
  7. clean:  
  8.         rm server $(object)  

客户端:

[cpp]  view plain copy
  1. object=client.o  
  2.   
  3. client.o:  
  4.         gcc -g -c client.c  
  5.         gcc -o client $(object)  
  6.   
  7. clean:  
  8.         rm -rf client $(object)  
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值