近期做了一个文件共享系统,要求需要有在linux系统下的服务器端和windows下的客户端,刚开始接到这个项目时。。。完全没有一点的概念,和以前做的小东西相比,这个项目相对要大很多,而且以前从来没有接触个linux环境的编程,再加上用Mysql的认证用户信息,这真是个大的挑战。现在,这个项目已经接近完成了,这其中有成功的喜悦,当然也积累了很多的经验,发现了自己在这方面欠缺很多东西。
首先学习了半个月的网络编程,通过自己的了解,发现linux下的套接字和windows下的套接字参数都是一样的,所有就在思考两者并联的可能性,实验了下,发现这是可行的,后来发现,socket基本都是基于最早的伯克利socket,所有实现跨平台的通信业就没什么奇怪的了。
对于并发这个问题,最开始的想法是用多线程,但是发现多线程的调用要比多进程要难,而刚开始适合挑一个门槛低一点的方式,因此在这次项目中选用了多进程,其实多线程这种方式在效率上会高很多。
mysql的安装也给我造成了很大的困难,困在这个问题上两三天,最后还是通过上网,终于发现我的乌班图系统自带的联网安装指令,这无疑是很方便的。当然最后也顺利了安装上了mysql。
这次项目遇到了很多问题,总的来说有如下几点:
1.程序代码杂乱无章,由于是刚开始学习这方面的内容,对语言的应用不够熟练,从各个地方直接拷贝来的东西很多,导致了程序没有整体统一的风格,一部分是linux风格,一部分是windows风格。
2.参数混乱,如上所述,对这次开发,始终还是前期准备工作不足,随便写了个程序流程图就急于完成,没有按照统一的标准,为了省时省事,没有给出实现函数的最优最规范方式,同时,基本上每个函数都没有参数,返回值也是随意定义的。
3.结构不合理,这个在后期我想要扩展更多功能的时候极大的影响了我,从这里了解到,一开始的结构设计有多么的重要。这点做的不好,很有可能导致我的项目需要全面的返工。因此希望在以后的设计总,多做前期工作,按照规范做。程序设计的慢点不要紧,关键是要一步一个较硬。
4.用户界面功能较少,用户不友好,这是本程序的致命问题,当然这并不能完全怪我,因为毕竟用控制台去写东西,始终还是没有GUI看着舒服,所有以后要多学习MFC并且去了解下各类的高级语言。以后争取做到系统稳定完善。。客户端美观大方。
总的来说,对自己一个月能取得这样的进步比较满意,但问题是存在也必须修正的,希望自己再接再励,争取下次做的更好。
下面是这次的代码
//******************************************************服务器端,需要环境,,gcc ,mysql,已经自定义的file文件
//gcc server.c -o server -I /usr/include/mysql -L /usr/lib -lmysqlclient
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LOG_PORTNUMBER 8888
#define HELLO_WORLD_SERVER_PORT 6666
#define LENGTH_OF_LISTEN_QUEUE 20
#define BUFFER_SIZE 1024
#define FILE_NAME_MAX_SIZE 512
#define PERMS S_IRUSR|S_IWUSR
void init_semaphore_struct(struct sembuf* sem,int semnum,int semop,int semflag)
{
sem->sem_num=semnum;
sem->sem_op=semop;
sem->sem_flg=semflag;
}
int del_semaphore(int semid)
{
#if 1
return semctl(semid,0,IPC_RMID);
#endif
}
int search_usrinf(char *name,char *password);
int file_download();
int server_upload();
int user_number=0;
int main(int argc,char **argv)
{
int sem_id,semop_ret,status;
struct sembuf semwait,semsignal;
if((sem_id=semget(IPC_PRIVATE,1,PERMS))==-1)
{
fprintf(stderr,"[%d]: access semophore error\n\a",getpid(),strerror(errno));
exit(1);
}
init_semaphore_struct(&semwait,0,-1,0);
init_semaphore_struct(&semsignal,0,1,0);
if(semop(sem_id,&semsignal,1)==-1)
{
fprintf(stderr,"[%d] increment semaphore error\n\a",getpid(),strerror(errno));
if(del_semaphore(sem_id)==-1)
{
fprintf(stderr,"[%d] destroy semaphore error\n\a",getpid(),strerror(errno));
}
exit(1);
}
int shmid;
char *p_addr;
if((shmid=shmget(IPC_PRIVATE,1024,PERMS))==-1)
{
fprintf(stderr,"create share memory error :%s \n\a",strerror(errno));
exit(1);
}
p_addr=shmat(shmid,0,0);
memset(p_addr,'\0',1024);
strcpy(p_addr,"0");
int sockfd,new_fd;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int sin_size;
char name[20],passwd[20];
if(argc!=1)
{
fprintf(stderr,"Usage %s portnumber\n\a",argv[0]);
exit(1);
}
/*if((portnumber=atoi(argv[1]))<0)
{
fprintf(stderr,"usage : %s hostname portnumber\n\a",argv[0]);
exit(1);
} */
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
fprintf(stderr,"Socket error %s \n\a",strerror(errno));
exit(1);
}
bzero(&server_addr,sizeof(struct sockaddr_in));
server_addr.sin_family=AF_INET;
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
server_addr.sin_port=htons(LOG_PORTNUMBER);
if((bind(sockfd,(struct sockaddr*)&server_addr,sizeof(struct sockaddr)))==-1)
{
fprintf(stderr,"bind error : %s \n\a",strerror(errno));
exit(1);
}
if(listen(sockfd,20)==-1)
{
fprintf(stderr,"Listen error: %s \n\a",strerror(errno));
exit(1);
}
while(1)
{
sin_size=sizeof(struct sockaddr_in);
if((new_fd=accept(sockfd,(struct sockaddr*)&client_addr,&sin_size))==-1)
{
fprintf(stderr,"Accept error: %s \n\a",strerror(errno));
exit(1);
}
else
{
semop_ret=semop(sem_id,&semwait,1);
p_addr=shmat(shmid,0,0);
user_number=atoi(p_addr);
user_number=(user_number+1)%1000;
sprintf(p_addr,"%d",user_number);
semop(sem_id,&semsignal,1);
printf("User number has increased to %d!!\n",user_number);
if(fork()==0)
{
fprintf(stderr,"Server get connection from %s \n\a",inet_ntoa(client_addr.sin_addr));
send(new_fd,"Please input your username:\0",strlen("Please input your username: \0"),0);
while(1)
{
if(recv(new_fd,name,20,0))
break;
}
send(new_fd,"Please input your password:\0",strlen("Please input password: \0"),0);
while(1)
{
if(recv(new_fd,passwd,20,0)>0)
break;
}
int flag=search_usrinf(name,passwd);
printf("flag=%d\n",flag);
if(flag==1)
{
//printf("*****user_number=%d\n",user_number);
char number[25];
bzero(number,25);
sprintf(number,"%d",user_number);
//printf("-----User number is %s!!----\n",number);
/*send(new_fd,number,25,0);*/
send(new_fd,"*********************************Log success!!*********************************\n\0",strlen("*********************************Log success!!*********************************\n\0"),0);
//******************************************
// start to serve
char buffer[100];
bzero(buffer,100);
recv(new_fd,buffer,100,0);
if(buffer[0]=='1')
{
send(new_fd,number,25,0);
printf("User number is %s!!\n",p_addr);
file_download();
}
if(buffer[0]=='2')
{
send(new_fd,number,25,0);
printf("User number is %s!!\n",p_addr);
server_upload();
}
if(buffer[0]=='3')
{
printf("Connect shut down!!\n");
return 1;
}
}
else if(flag==0)
{
send(new_fd,"Pass word error!!\n",strlen("Pass word error!!\n"),0);
break;
}
else
{
send(new_fd,"User does not exit!!!\n",strlen("User does not exit!!!\n"),0);
break;
}
close(new_fd);
}
}
}
if(del_semaphore(sem_id)==-1)
fprintf(stderr,"[%d] destroy semaphore error\n\a",getpid(),strerror(errno));
close(sockfd);
return 1;
}
int search_usrinf(char *name,char *password)
{
MYSQL mysql;
MYSQL_RES *res;
MYSQL_ROW row;
char sql[100];
int t;
sprintf(sql,"select passwd from usrinf where usr_name=\"%s\"\0",name);
mysql_init(&mysql); //初始化mysql结构
if(!mysql_real_connect(&mysql,"localhost","root","duanmaotao","usr_infor",3306,NULL,0))
printf("\nData base connect error: %s\n",mysql_error(&mysql));
else
printf("\nData base connect!\n");
t = mysql_real_query(& mysql, sql, (unsigned int)strlen(sql)); //在服务器上执行定义的SQL语句
if(t)
printf("select error: %s\n",mysql_error(&mysql));
else
{
res = mysql_store_result(&mysql);
row = mysql_fetch_row(res);
if(row==NULL)
{
printf("User does not exit!!!\n");
printf("Release database...\n\n");
mysql_free_result(res);
mysql_close(&mysql);
return -1;
}
else if(strcmp(password,row[0])==0)
{
printf("Log in\n");
printf("Release database...\n\n");
mysql_free_result(res);
mysql_close(&mysql);
return 1;
}
else
{
printf("Passwd error!\n");
printf("Release database...\n\n");
mysql_free_result(res);
mysql_close(&mysql);
return 0;
}
}
}
int file_download()
{
int sockSrv=socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in addrSrv;
bzero(&addrSrv,sizeof(addrSrv));
addrSrv.sin_addr.s_addr=htons(INADDR_ANY);
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(7777+user_number);
if(bind(sockSrv,(struct sockaddr*)&addrSrv,sizeof(addrSrv))==-1)
{
printf("Bind error!!\n");
return 0;
}
listen(sockSrv,20);
struct sockaddr_in addrClient;
int len=sizeof(struct sockaddr);
int from_fd,file_fd;
int bytes_read,bytes_write;
char buffer[BUFFER_SIZE];
char *ptr;
char file_name[20];
memset(file_name,'\0',20);
while(1)
{
int sockConn=accept(sockSrv,(struct sockaddr*)&addrClient,&len);
printf("Connect to %s... \n",inet_ntoa(addrClient.sin_addr));
bzero(buffer,1024);
if((file_fd=open("./file/filename",O_RDONLY ))==-1)
{
//fprintf(stderr,"Open %s error %s\n",argv[1],strerror(errno));
printf("File information can not open!!\n");
close(sockConn);
return 0;
}
bytes_read=read(file_fd,buffer,BUFFER_SIZE);
buffer[bytes_read]='\0';
send(sockConn,buffer,bytes_read+1,0);
close(file_fd);
recv(sockConn,file_name,20,0);
if((from_fd=open(file_name,O_RDONLY ))==-1)
{
//fprintf(stderr,"Open %s error %s\n",argv[1],strerror(errno));
close(sockConn);
return 0;
}
while(bytes_read=read(from_fd,buffer,BUFFER_SIZE))
{
printf("Server has transfered %d bytes to %s\n",bytes_read,inet_ntoa(addrClient.sin_addr));
if((bytes_read==-1)) break;
else if(bytes_read>0)
{
ptr=buffer;
while(bytes_write=send(sockConn,ptr,bytes_read,0))
{
if((bytes_write==-1)) break;
else if(bytes_write==bytes_read)
{
break;
}
else if(bytes_write>0)
{
ptr+=bytes_write;
bytes_read-=bytes_write;
}
}
if(bytes_write==-1) break;
}
}
if(bytes_write!=-1&&bytes_read!=-1)
{
printf("Server has transfered %s to %s!\n",file_name,inet_ntoa(addrClient.sin_addr));
printf("\n");
close(sockConn);
printf("Sock closed!\n\n");
break;
}
else
{
close(sockConn);
break;
}
}
close(from_fd);
return 1;
}
int server_upload()
{
int to_fd,file_fd;
int bytes_read,bytes_write;
char buffer[BUFFER_SIZE];
char *ptr;
int sockClient=socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in addrSrv;
bzero(&addrSrv,sizeof(addrSrv));
addrSrv.sin_addr.s_addr=inet_addr("192.168.220.2");
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(7777+user_number);
connect(sockClient,(struct sockaddr*)&addrSrv,sizeof(struct sockaddr));
char file_name[20];
bzero(file_name,20);
recv(sockClient,file_name,20,0);
if((file_fd=open("./file/filename",O_RDWR | O_APPEND,S_IRUSR|S_IWUSR ))==-1)
{
printf("File_information can not found!\n");
return 0;
}
char file_info[BUFFER_SIZE];
bzero(file_info,BUFFER_SIZE);
read(file_fd,file_info,BUFFER_SIZE);
sprintf(file_name,"\n%s",file_name);
if(strstr(file_info,file_name)==NULL)
write(file_fd,file_name,strlen(file_name));
close(file_fd);
if((to_fd=open(file_name,O_RDWR | O_CREAT,S_IRUSR|S_IWUSR ))==-1)
{
printf("File not found!\n");
return 0;
}
while(bytes_read=recv(sockClient,buffer,BUFFER_SIZE,0))
{
if((bytes_read==-1)) break;
else if(bytes_read>0)
{
ptr=buffer;
while(bytes_write=write(to_fd,ptr,bytes_read))
{
if((bytes_write==-1)) break;
else if(bytes_write==bytes_read) break;
else if(bytes_write>0)
{
ptr+=bytes_write;
bytes_read-=bytes_write;
}
}
if(bytes_write==-1) break;
}
}
if(bytes_write!=-1&&bytes_read!=-1)
{
printf("Server has received %s from %s\n",file_name,inet_ntoa(addrSrv.sin_addr));
}
close(sockClient);
close(to_fd);
return 1;
}