Socket网络编程--小小网盘程序(2)
来源:互联网 发布:c语言视频夏老师 编辑:程序博客网 时间:2024/04/29 00:03
http://www.cnblogs.com/wunaozai/p/3887728.html
这一节将不会介绍太多的技术的问题,这节主要是搭建一个小小的框架,为了方便接下来的继续编写扩展程序。本次会在上一小节的基础上加上一个身份验证的功能。
因为网盘程序不像聊天程序,网盘是属于主动向服务器拉取信息,而聊天程序有可能要被动获取信息,所以为了减轻服务器压力,每次要向服务器获取服务就建立一个短连接,而不像聊天程序一样的长连接,微信的公众平台,输入指令获取服务,就是这个样子了。具体看一下代码就知道了。
还有为了方便处理,我增加了一个控制信号,这个控制信号在以前的聊天程序中讲到过,但是当时为了简单就没有实现,现在就简单实现一些,方便以后可以参考。
还有就是这次的网盘程序我将尽量实现下面的这些功能:
(1) file push filename //用户上传文件到服务器上
(2) file pull filename //用户下载文件到本地上
(3) file list //列出用户在服务器中的所有文件
(4) file sendto filename username //共享文件给其他用户
(5) file delete filename //删除服务器中的文件
(6) 用户登录,自动完成
本次数据库名为filetranslate,目前有表user
1 create table user2 (3 uid int;4 username varchar(64);5 password varchar(64); 6 );
修改后的client.cpp
1 #include <netinet/in.h> // sockaddr_in 2 #include <sys/types.h> //socket 3 #include <sys/socket.h> //socket 4 #include <netdb.h> //gethostbyname 5 #include <unistd.h> //close 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <string.h> 9 #include <time.h> 10 #include <arpa/inet.h> //inet_addr 11 12 #define SERVVER_PORT 12138 13 #define LISTEN_QUEUE 20 14 #define BUFFER_SIZE 1024 15 16 //传输控制信号宏定义 17 //struct Control中control的取值 18 #define USER_CHECK_LOGIN 1 19 #define FILE_PUSH 2 20 #define FILE_PULL 3 21 #define FILE_LIST 4 22 #define FILE_SENDTO 5 23 #define FILE_DELECT 6 24 25 struct Addr 26 { 27 char host[64]; 28 int port; 29 }; 30 struct User 31 { 32 int uid; 33 char username[64]; 34 char password[64]; 35 }; 36 struct Control 37 { 38 int uid; 39 int control; 40 }; 41 42 void print_time(char *ch);//打印时间 43 int file_push(struct Addr addr,struct User user,char *filenames); 44 int check_login(struct Addr addr,struct User * user); 45 46 47 int main(int argc,char *argv[]) 48 { 49 char orderbuf[BUFFER_SIZE]; 50 struct Addr addr; 51 char arg1[32],arg2[32],arg3[32],arg4[32]; 52 struct User user; 53 54 if(argc!=5) 55 { 56 perror("usage: ./client [serverhost] [serverport] [username] [password]"); 57 exit(-1); 58 } 59 strcpy(addr.host,argv[1]); 60 addr.port=atoi(argv[2]); 61 strcpy(user.username,argv[3]); 62 strcpy(user.password,argv[4]); 63 int uid=check_login(addr,&user); 64 if(uid<=0) 65 { 66 perror("用户验证失败"); 67 exit(-1); 68 } 69 printf("验证登陆成功\n"); 70 while(1) 71 { 72 printf("\n请输入操作指令:"); 73 fgets(orderbuf,BUFFER_SIZE,stdin); 74 memset(arg1,0,sizeof(arg1)); 75 memset(arg2,0,sizeof(arg2)); 76 memset(arg3,0,sizeof(arg3)); 77 memset(arg4,0,sizeof(arg4)); 78 sscanf(orderbuf,"%s%s%s%s",arg1,arg2,arg3,arg4); 79 if(strcmp(arg1,"file")==0) 80 { 81 if(strcmp(arg2,"push")==0) 82 { 83 strcpy(orderbuf,arg3); 84 file_push(addr,user,orderbuf); 85 } 86 else if(strcmp(arg2,"pull")==0) 87 { 88 ; 89 } 90 else if(strcmp(arg2,"list")==0) 91 { 92 ; 93 } 94 else if(strcmp(arg2,"sendto")==0) 95 { 96 ; 97 } 98 else if(strcmp(arg2,"delect")==0) 99 {100 ;101 }102 else103 {104 printf("该命令不支持\n");105 }106 }107 else108 {109 printf("该命令不支持\n");110 }111 }112 113 114 return 0;115 }116 117 //验证成功时返回大于0的uid号码,错误返回-1118 int check_login(struct Addr addr,struct User * user)119 {120 struct sockaddr_in servAddr;121 struct hostent * host;122 struct Control control;123 int sockfd;124 125 host=gethostbyname(addr.host);126 servAddr.sin_family=AF_INET;127 servAddr.sin_addr=*((struct in_addr *)host->h_addr);128 //servAddr.sin_addr.s_addr=inet_addr("127.0.0.1");129 servAddr.sin_port=htons(addr.port);130 if(host==NULL)131 {132 perror("获取IP地址失败");133 exit(-1);134 }135 if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)136 {137 perror("socket创建失败");138 exit(-1);139 }140 if(connect(sockfd,(struct sockaddr *)&servAddr,sizeof(struct sockaddr_in))==-1)141 {142 perror("connect 失败");143 exit(-1);144 }145 146 control.control=USER_CHECK_LOGIN;147 control.uid=0;148 if(send(sockfd,(char *)&control,sizeof(struct Control),0)<0)149 {150 perror("发送数据失败");151 exit(-1);152 }153 154 if(send(sockfd,(char *)user,sizeof(struct User),0)<0)155 {156 perror("发送数据失败");157 exit(-1);158 }159 bzero(user,sizeof(struct User));160 if(recv(sockfd,(char *)user,sizeof(struct User),0)<0)161 {162 perror("接收数据失败");163 exit(-1);164 }165 printf("获取后用户名:%s 密码:%s ID号:%d\n",user->username,user->password,user->uid);166 167 close(sockfd);//关闭socket连接168 return user->uid;169 }170 171 int file_push(struct Addr addr,struct User user,char *filenames)172 {173 struct sockaddr_in servAddr;174 struct hostent * host;175 struct Control control;176 int sockfd;177 FILE *fp;178 179 host=gethostbyname(addr.host);180 servAddr.sin_family=AF_INET;181 servAddr.sin_addr=*((struct in_addr *)host->h_addr);182 //servAddr.sin_addr.s_addr=inet_addr("127.0.0.1");183 servAddr.sin_port=htons(addr.port);184 if(host==NULL)185 {186 perror("获取IP地址失败");187 exit(-1);188 }189 if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)190 {191 perror("socket创建失败");192 exit(-1);193 }194 195 if(connect(sockfd,(struct sockaddr *)&servAddr,sizeof(struct sockaddr_in))==-1)196 {197 perror("connect 失败");198 exit(-1);199 }200 201 //打开文件202 if((fp=fopen(filenames,"rb"))==NULL)203 {204 perror("文件打开失败");205 exit(-1);206 }207 //这里传输控制信号208 control.control=FILE_PUSH;209 control.uid=user.uid;210 if(send(sockfd,(char *)&control,sizeof(struct Control),0)<0)211 {212 perror("控制信号发送失败");213 exit(-1);214 }215 char buffer[BUFFER_SIZE];216 bzero(buffer,BUFFER_SIZE);217 printf("正在传输文件");218 int len=0;219 //不断的读取文件直到文件结束220 while((len=fread(buffer,1,BUFFER_SIZE,fp))>0)221 {222 if(send(sockfd,buffer,len,0)<0)223 {224 perror("发送数据失败");225 exit(-1);226 }227 bzero(buffer,BUFFER_SIZE);228 printf(".");//1K打印一个点//如果要实现百分比,就要计算文件大小,然后再处理即可229 }230 231 printf("传输完毕\n");232 fclose(fp);//关闭文件流233 close(sockfd);//关闭socket连接234 235 return 0;236 }237 238 void print_time(char *ch)239 {240 time_t now;241 struct tm * stm;242 time(&now);243 stm=localtime(&now);244 sprintf(ch,"%02d:%02d:%02d\n",stm->tm_hour,stm->tm_min,stm->tm_sec);245 return ;246 }
下面这个是server.cpp
1 #include <netinet/in.h> 2 #include <sys/types.h> 3 #include <sys/socket.h> 4 #include <sys/select.h> 5 #include <netdb.h> 6 #include <stdlib.h> 7 #include <time.h> 8 #include <string.h> 9 #include <unistd.h> 10 #include <stdio.h> 11 #include <arpa/inet.h> //inet_ntoa 12 #include <mysql.h> 13 14 #define SERVER_PORT 12138 15 #define LISTEN_QUEUE 20 16 #define BACKLOG 200 17 #define BUFFER_SIZE 1024 18 19 //传输控制信号宏定义 20 //struct Control中control的取值 21 #define USER_CHECK_LOGIN 1 22 #define FILE_PUSH 2 23 #define FILE_PULL 3 24 #define FILE_LIST 4 25 #define FILE_SENDTO 5 26 #define FILE_DELECT 6 27 28 struct User 29 { 30 int uid; 31 char username[64]; 32 char password[64]; 33 }; 34 35 struct Control 36 { 37 int uid; 38 int control; 39 }; 40 41 void print_time(char *ch);//打印时间 42 int MAX(int a,int b); 43 int mysql_check_login(struct User user); 44 45 46 int main(int argc,char *argv[]) 47 { 48 struct sockaddr_in server_addr; 49 struct sockaddr_in client_addr; 50 struct User user; 51 struct Control control; 52 char ch[64]; 53 int clientfd; 54 pid_t pid; 55 socklen_t length; 56 bzero(&server_addr,sizeof(server_addr)); 57 server_addr.sin_family=AF_INET; 58 server_addr.sin_addr.s_addr=htons(INADDR_ANY); 59 server_addr.sin_port=htons(SERVER_PORT); 60 61 //创建套接字 62 int sockfd=socket(AF_INET,SOCK_STREAM,0); 63 if(sockfd<0) 64 { 65 perror("创建套接字失败"); 66 exit(-1); 67 } 68 69 if(bind(sockfd,(struct sockaddr *)&server_addr,sizeof(server_addr))==-1) 70 { 71 perror("bind 失败"); 72 exit(-1); 73 } 74 75 if(listen(sockfd,LISTEN_QUEUE)) 76 { 77 perror("listen 失败"); 78 exit(-1); 79 } 80 81 length=sizeof(struct sockaddr); 82 83 while(1) 84 { 85 clientfd=accept(sockfd,(struct sockaddr *)&client_addr,&length); 86 if(clientfd==-1) 87 { 88 perror("accept 失败"); 89 continue; 90 } 91 printf(">>>>>%s:%d 连接成功,当前所在的ID(fd)号: %d \n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port),clientfd); 92 print_time(ch); 93 printf("加入的时间是:%s\n",ch); 94 95 //来一个连接就创建一个进程进行处理 96 pid=fork(); 97 if(pid<0) 98 { 99 perror("fork error");100 }101 else if(pid==0)102 {103 recv(clientfd,(char *)&control,sizeof(struct Control),0);104 printf("用户 %d 使用命令 %d\n",control.uid,control.control);105 switch(control.control)106 {107 case USER_CHECK_LOGIN:108 {109 //身份验证处理110 recv(clientfd,(char *)&user,sizeof(struct User),0);111 printf("客户端发送过来的用户名是:%s,密码:%s\n",user.username,user.password);112 if((user.uid=mysql_check_login(user))>0)113 {114 printf("验证成功\n");115 }116 else117 {118 printf("验证失败\n");119 }120 send(clientfd,(char *)&user,sizeof(struct User),0);121 break;122 }123 case FILE_PUSH:124 {125 char buffer[BUFFER_SIZE];126 int data_len;127 FILE * fp=NULL;128 bzero(buffer,BUFFER_SIZE);129 if((fp=fopen("data","wb"))==NULL)130 {131 perror("文件打开失败");132 exit(-1);133 }134 //循环接收数据135 int size=0;//表示有多少个块136 while(data_len=recv(clientfd,buffer,BUFFER_SIZE,0))137 {138 if(data_len<0)139 {140 perror("接收数据错误");141 exit(-1);142 }143 size++;144 if(size==1)145 printf("正在接收来自%s:%d的文件\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));146 else147 printf(".");148 //向文件中写入149 int write_len=fwrite(buffer,sizeof(char),data_len,fp);150 if(write_len>data_len)151 {152 perror("写入数据错误");153 exit(-1);154 }155 bzero(buffer,BUFFER_SIZE);156 }157 if(size>0)158 printf("\n%s:%d的文件传送完毕\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));159 else160 printf("\n%s:%d的文件传送失败\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));161 fclose(fp);162 //rename("data","asdf");//这里可以修改文件的名字163 exit(0);164 break;165 }166 case FILE_PULL:167 {168 break;169 }170 case FILE_LIST:171 {172 break;173 }174 case FILE_DELECT:175 {176 break;177 }178 default:179 {180 break;181 }182 }183 close(clientfd);//短连接结束184 exit(0);//退出子进程185 }186 }187 188 return 0;189 }190 191 192 //函数定义193 int mysql_check_login(struct User user)194 {195 MYSQL conn;196 MYSQL_RES *res_ptr;197 MYSQL_ROW result_row;198 int res;199 int row;200 int column;201 int uid;202 char sql[256]={0};203 strcpy(sql,"select uid from users where username=\"");204 strcat(sql,user.username);205 strcat(sql,"\" and password=\"");206 strcat(sql,user.password);207 strcat(sql,"\";");208 printf("查询的sql:%s\n",sql);209 uid=-1;210 mysql_init(&conn);211 if(mysql_real_connect(&conn,"localhost","root","","filetranslate",0,NULL,CLIENT_FOUND_ROWS))212 {213 res=mysql_query(&conn,sql);214 if(res)215 {216 perror("Select SQL ERROR!");217 exit(-1);218 }219 else220 {221 res_ptr=mysql_store_result(&conn);222 if(res_ptr)223 {224 column=mysql_num_fields(res_ptr);//获取列数225 row=mysql_num_rows(res_ptr)+1;//获取行数,加1表示还有第一行字段名226 if(row<=1)227 {228 ;//验证失败229 }230 else231 {232 //这里先假定username是唯一233 result_row=mysql_fetch_row(res_ptr);234 printf("获取到的uid是:%s\n",result_row[0]);235 uid=atoi(result_row[0]);236 }237 }238 else239 {240 printf("没有查询到匹配的数据\n");241 }242 }243 }244 else245 {246 perror("Connect Failed!\n");247 exit(-1);248 }249 mysql_close(&conn);250 return uid;251 }252 253 void print_time(char *ch)254 {255 time_t now;256 struct tm * stm;257 time(&now);258 stm=localtime(&now);259 sprintf(ch,"%02d:%02d:%02d\n",stm->tm_hour,stm->tm_min,stm->tm_sec);260 return ;261 }262 263 int MAX(int a,int b)264 {265 if(a>b)266 return a;267 return b;268 }
下面给张运行时的截图
关于c语言调用mysql: http://www.cnblogs.com/wunaozai/p/3876134.html
本文地址: http://www.cnblogs.com/wunaozai/p/3887728.html
- Socket网络编程--小小网盘程序(2)
- Socket网络编程--小小网盘程序(1)
- Socket网络编程--小小网盘程序(1)
- Socket网络编程--小小网盘程序(3)
- Socket网络编程--小小网盘程序(4)
- Socket网络编程--小小网盘程序(5)
- socket网络编程2
- 网络编程(2)-socket
- Linux 网络程序编程初步 Socket
- java 聊天程序 socket网络编程
- 网络socket编程之TCP示例程序
- 基于socket网络编程的文件传输程序
- 网络编程之小小示例
- 小小的java socket聊天程序
- linux网络编程--socket(2)
- 网络编程 Socket编程指南及示例程序
- 网络编程---Socket编程
- 网络编程:Socket编程
- 副本集RAFT协议的实现(2):选主,主从切换
- java 三角形 异常处理
- Hadoop2.x 一些知识,MapReduce历史服务配置启动查看,YARN的日志聚集功能配置使用
- leetcode6 [zigzag]@python
- opencv findcontour查找最大的内轮廓
- Socket网络编程--小小网盘程序(2)
- MySQL数据库使用的一些基础
- Linux 安装navicat
- python中文分词,使用结巴分词对python进行分词
- Socket网络编程--小小网盘程序(3)
- java.lang.OutOfMemoryError: PermGen space: java reflection
- 第十课:VueX初始化歌手数据的配置
- HTTP Content-Type
- Wannafly模拟赛5 A split 二分