1.登录模块设计
- 输入用户名和密码
- 根据用户名从数据库提取密码
- 比较用户输入密码和数据库提取密码,以决定是否登录成功
2.编译客户端程序
- arm-linux-gcc
- -L ../../008/openssl-1.0.0s/_install/lib/ -lssl -lcrypto
- -I ../../008/openssl-1.0.0s/_install/include/
- -L ../../010/sqlite-autoconf-3070800/_install/lib/ -lsqlite3
- -I ../../010/sqlite-autoconf-3070800/_install/include/
- client.c -o client
3.创建数据库
- ./test_db user.db "create table tb0(name varchar(10),passwd varchar(10));".
4.插入数据
- ./test_db user.db "insert into tb0 values('xxx','123');"
- ./test_db user.db "insert into tb0 values('xxx','456');"
- ./test_db user.db "insert into tb0 values('xxx','789');"
5.改进的客户端代码
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <sqlite3.h>
#define port 3333
int sockclient;
struct sockaddr_in sockaddr1;
char ipaddr[15];
SSL_CTX *ctx;
SSL *ssl;
int linkS()
{
if((sockclient=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("socket");
exit(0);
}
memset(&sockaddr1,0,sizeof(sockaddr1));
sockaddr1.sin_family = AF_INET;
sockaddr1.sin_addr.s_addr = inet_addr(ipaddr);
sockaddr1.sin_port = htons(port);
if(connect(sockclient,(struct sockaddr* )&sockaddr1,sizeof(sockaddr1))==-1)
{
perror("connect");
exit(0);
}
// 创建SSL
ssl = SSL_new(ctx);
SSL_set_fd(ssl, sockclient);
SSL_connect(ssl);
return 1;
}
//~~~~~~~~~~~~~~~~~~~~~~~上传文件~~~~~~~~~~~~~~~~~~~~~~~~~
void upload_file(char *filename)
{
int fd;
char buf[1024];
int count=0;
int size = strlen(filename);
char cmd = 'U';
struct stat fstat;
if((fd=open(filename,O_RDONLY))==-1)
{
perror("open: ");
return;
}
/*发送上传命令*/
// write(sockclient,&cmd,1);
SSL_write(ssl,&cmd,1);
/*发送文件名*/
// write(sockclient,(void *)&size,4);
// write(sockclient,filename,size);
SSL_write(ssl,(void *)&size,4);
SSL_write(ssl,filename,size);
/*发送文件长度*/
if(stat(filename,&fstat)==-1)
return;
// write(sockclient,(void *)&(fstat.st_size),4);
SSL_write(ssl,(void *)&(fstat.st_size),4);
/*发送文件内容*/
while((count=read(fd,(void *)buf,1024))>0)
{
// write(sockclient,&buf,count);
SSL_write(ssl,&buf,count);
}
close(fd);
}
//~~~~~~~~~~~~~~~~~~~~~~~下载文件~~~~~~~~~~~~~~~~~~~~~~~~~
void download_file(char *filename)
{
int fd;
char buf[1024];
int count=0;
int filesize = 0;
int tmpsize = 0;
int namesize = 0;
char cmd = 'D';
int size = strlen(filename);
/*发送下载命令*/
// write(sockclient,(void *)&cmd,1);
SSL_write(ssl,(void *)&cmd,1);
/*发送文件名*/
// write(sockclient,&size,4);
// write(sockclient,filename,size);
SSL_write(ssl,&size,4);
SSL_write(ssl,filename,size);
/*创建文件*/
if((fd=open(filename,O_RDWR|O_CREAT,0777))<0)
{
perror("open error:\n");
}
/*接收文件长度*/
// read(sockclient,&filesize,4);
SSL_read(ssl,&filesize,4);
while((count=SSL_read(ssl,(void *)buf,1024))>0)
{
write(fd,&buf,count);
tmpsize += count;
if(tmpsize==filesize)
break;
}
close(fd);
}
void quit()
{
char cmd = 'Q';
// write(sockclient,(void *)&cmd,1);
SSL_write(ssl,(void *)&cmd,1);
system("clear");
// 关闭SSL
SSL_shutdown(ssl);
SSL_free(ssl);
close(sockclient);
SSL_CTX_free(ctx);
exit(0);
}
void menu()
{
char command;
char file_u[30];
char file_d[30];
char tmp;
char c;
while(1)
{
printf("\n------------------------------ 1.Upload Files ------------------------------\n");
printf("------------------------------ 2.Download Files ------------------------------\n");
printf("------------------------------ 3.Exit ------------------------------------\n");
printf("Please input the Client command:");
command=getchar();
switch(command)
{
case '1':
{
printf("Upload File:");
while ((c=getchar()) != '\n' && c != EOF);
fgets(file_u,30,stdin);
file_u[strlen(file_u)-1]='\0';
upload_file(file_u);
}
break;
case '2':
{
printf("Download Files:");
while ((c=getchar()) != '\n' && c != EOF);
fgets(file_d,sizeof(file_d),stdin);
file_d[strlen(file_d)-1]='\0';
download_file(file_d);
}
break;
case '3':
quit();
break;
default:
printf("Please input right command\n");
break;
}
}
}
char passwd_d[10];
static int callback(void *NotUsed, int argc, char **argv, char **azColName)
{
int i;
for (i=0; i<argc; i++)
{
// printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
strcpy(passwd_d, argv[i]);
}
printf("\n");
return 0;
}
int login()
{
char username[10];
char passwd[10];
sqlite3 *db;
char sql[50];
int success;
//1. 通知用户输入用户名和密码
printf("User name: ");
scanf("%s",username);
printf("Password: ");
scanf("%s",passwd);
//2. 根据用户名,从数据库提取正确的密码
sprintf(sql, "select passwd from tb0 where name='%s';", username);
sqlite3_open("user.db", &db);
sqlite3_exec(db, sql, callback, 0, NULL);
sqlite3_close(db);
//3. 比较用户输入的密码和数据库提取出的密码,以决定是否登录成功
success = strcmp(passwd, passwd_d);
return success;
}
int main(int argc,char *args[])
{
if(argc!=2)
{
printf("format error: you mast enter ipaddr like this : client 192.168.0.111\n");
exit(0);
}
strcpy(ipaddr,args[1]);
if (login() != 0)
{
printf("wrong username or password!\n");
exit(0);
}
// SSL库初始化
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
ctx = SSL_CTX_new(SSLv23_client_method());
linkS();
menu();
return 0;
}