网络通信小项目---TCP简单云盘
最近在学linux下的网络编程,做了一个小小的项目,记录一下。
项目名称:局域网下云盘
项目功能:用户输入用户名和密码登录,成功后连接文件服务器,进行文件的上传和下载
客户端:
开始界面:
根据用户输入的命令进行相应的操作,将想要做的事情传递到服务器端,服务器将会处理用户的命令,并给予反馈。
------------------------------------------------------------------------------------------------------------------
//注册
int zhuce(int sockfd1)
{
char buf[100] = {0};
strcpy(buf,"1");
write(sockfd1,buf,100);//向服务器发送1代表要进行注册
printf("username&passwd> ");
fflush(stdout);
memset(buf,0,sizeof(buf));
gets(buf);
write(sockfd1,buf,100);//发送要注册的用户名和密码
read(sockfd1,buf,100);//读取服务器的反馈
if(0 == strncmp(buf,"ok",2))
{
printf("zhuce is ok\n");
}
else if(0 == strncmp(buf,"no",2))
{
printf("zhuce is failed\n");
return 0;
}
return 0;
}
----------------------------------------------------------------------------------------------------------------
//登录
int login(int sockfd1)
{
char buf[100] = {0};
strcpy(buf,"2");
write(sockfd1,buf,100);//向服务器发送2代表要进行登录
printf("username&passwd> ");
fflush(stdout);
memset(buf,0,sizeof(buf));
gets(buf);
write(sockfd1,buf,100);//发送要注册的用户名和密码
read(sockfd1,buf,100);//读取服务器的反馈
printf("%s\n",buf);
if(0 == strncmp(buf,"ok",2))
{
printf("login is ok\n");
return 1;//返回1便于登录文件服务器判断
}
else if(0 == strncmp(buf,"no",2))
{
printf("username or passwd is failed\n");
return 0;
}
return 0;
}
------------------------------------------------------------------------------------------------------------------
//修改密码
int update(int sockfd1)
{
char buf[100] = {0};
strcpy(buf,"3");
write(sockfd1,buf,100);//向服务器发送3代表要修改密码
printf("username&passwd> ");
fflush(stdout);
memset(buf,0,sizeof(buf));
gets(buf);
write(sockfd1,buf,100);//发送要注册的用户名和密码
read(sockfd1,buf,100);//读取服务器的反馈
if(0 == strncmp(buf,"ok",2))
{
printf("change is ok\n");
}
else if(0 == strncmp(buf,"no",2))
{
printf("change is failed\n");
return 0;
}
return 0;
}
登录验证成功后
和登录数据库服务器一样,将向要进行的操作传递给文件服务器,让它进行相应的操作,并给予反馈。
//上传文件
void up_file(int sockfd,char *buf);
//下载文件
void down_file(int sockfd, char *buf);
//查看服务器上所有文件
void list_file(int sockfd,char *buf);
//查看本地文件
void ls_file(int sockfd,char *buf);
-----------------------------------------------------------------------------------------------------------------
服务器:
拥有两个并行的服务器数据库服务器和文件服务器,使用多进行实现并发。
用户一连接成功,就进行fork,创建子进程,用来进行用户注册和登录验证处理。
父进程进行用户登录成功后的文件服务器操作,互不影响。
1.数据库服务器:
用来进行存储用户名和密码,这里采取了linux下常见的sqlite3数据库进行支撑。
用户连接上数据库服务器后,创建一张存放用户名和密码的表名为user,如果已存在则不创建。
用户登录进来后也进行fork创建子进程处理相应的事物,而父进程则负责监听连接下个用户的接入。
//注册后在数据库插入信息
int creat_list(int sqlfd)
{
sqlite3 *db;
if(sqlite3_open("my.db", &db) != SQLITE_OK)
{
printf("error : %s\n", sqlite3_errmsg(db));
exit(-1);
}
char sqlbuf[100] = {0};
char sbuf[10] = {0};
char cbuf[10] = {0};
char *errmsg;
read(sqlfd,sqlbuf,sizeof(sqlbuf));
myc(sqlbuf,' ',sbuf,cbuf);
sprintf(sqlbuf,"insert into user values('%s','%s');",sbuf,cbuf);
if(sqlite3_exec(db, sqlbuf, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("error : %s\n", errmsg);
char buf[100] = {0};
strcpy(buf,"no");
write(sqlfd,buf,100);
return 0;
}
else
{
char buf[100] = {0};
strcpy(buf,"ok");
write(sqlfd,buf,100);
sqlite3_close(db);
}
}
------------------------------------------------------------------------------------------------------------
//验证登录
int login(int sqlfd)
{
sqlite3 *db;
//打开或创建数据库
if(sqlite3_open("my.db", &db) != SQLITE_OK)
{
printf("error : %s\n", sqlite3_errmsg(db));
exit(-1);
}
char sqlbuf[100] = {0};
char sbuf[10] = {0};
char cbuf[10] = {0};
char *errmsg;
char **result;
int a,b;
read(sqlfd,sqlbuf,sizeof(sqlbuf));
myc(sqlbuf,' ',sbuf,cbuf);//将读到的用户名和密码分割
sprintf(sqlbuf,"select * from user where name = '%s' and passwd = '%s';",sbuf,cbuf);
if(sqlite3_get_table(db, sqlbuf,&result,&a,&b, &errmsg) != SQLITE_OK)
{
printf("error : %s\n", errmsg);
exit(-1);
}
//如果没有找到记录
if(a == 0)
{
char buf[100] = {0};
strcpy(buf,"no");
write(sqlfd,buf,100);
sqlite3_close(db);
}
else//找到记录
{
char buf[100] = {0};
strcpy(buf,"ok");
write(sqlfd,buf,100);
//sleep(1);
sqlite3_close(db);
}
}
-------------------------------------------------------------------------------------------------------------
//修改密码
int change_passwd(int sqlfd)
{
sqlite3 *db;
if(sqlite3_open("my.db", &db) != SQLITE_OK)
{
printf("error : %s\n", sqlite3_errmsg(db));
exit(-1);
}
char sqlbuf[100] = {0};
char sbuf[10] = {0};
char cbuf[10] = {0};
char *errmsg;
read(sqlfd,sqlbuf,sizeof(sqlbuf));
myc(sqlbuf,' ',sbuf,cbuf);
sprintf(sqlbuf,"update user set passwd = '%s' where name = '%s';",cbuf,sbuf);
if(sqlite3_exec(db, sqlbuf, NULL, NULL, &errmsg) != SQLITE_OK)
{
printf("error : %s\n", errmsg);
char buf[100] = {0};
strcpy(buf,"no");
write(sqlfd,buf,100);
return 0;
}
else
{
char buf[100] = {0};
strcpy(buf,"ok");
write(sqlfd,buf,100);
sqlite3_close(db);
}
}
2.文件服务器:
使得用户能够进行对文件的一系列操作。
用户登录进来同样进行fork创建子进程处理相应的事物,而父进程则负责监听连接下个用户的接入。
//上传文件
if(0 == strncmp(buf,"up",2))
{
char filename[20] = {0};
strcpy(filename,buf+3);
read(clientfd,buf,sizeof(buf));
int size = atoi(buf);
int fd = open(filename,O_CREAT|O_RDWR,0666);
while(size)
{
int n = read(clientfd,buf,sizeof(buf));
write(fd,buf,n);
size -= n;
}
close(fd);
}
-------------------------------------------------------------------------------------------------------
//下载文件
if(0 == strncmp(buf, "down", 4) )
{
char filename[20] = {0};
strcpy(filename, buf+5);
//send file size
struct stat s;
stat(filename, &s);
sprintf(buf, "%ld", s.st_size);
write(clientfd, buf, sizeof buf);
//send file data
int n;
int fd = open(filename, O_RDONLY);
while(n = read(fd, buf, sizeof buf))
write(clientfd, buf, n);
close(fd);
}
--------------------------------------------------------------------------------------------------------
//展示服务器上的文件
if(0 == strncmp(buf,"list",4))
{
memset(buf,0,sizeof(buf));
int filenum = 0;
DIR *dir;
struct dirent *dp;
dir = opendir(".");
while((dp = readdir(dir)) != NULL)
{
if(dp->d_name[0] == '.')
{
continue;
}
filenum++;
}
sprintf(buf,"%d",filenum);
write(clientfd,buf,100);
closedir(dir);
dir = opendir(".");
while((dp = readdir(dir)) != NULL)
{
if(dp->d_name[0] == '.')
{
continue;
}
memset(buf,0,sizeof(buf));
strcat(buf,dp->d_name);
write(clientfd,buf,100);
}
closedir(dir);
}
------------------------------------------------------------------------------------------------------------
虽然写的有点low,但是算是一个比较好的入门的小项目,希望大家多多指教,互相交流学习。