#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#define PORT 3001 //*客户机连接远程主机的端口 */
#define MAXDATASIZE 128 //* 每次可以接收的最大字节 */
#define BACKLOG 3 //*定义最大连接数量*/
#define USRNUM 3
struct usr_pas /*定义用户结构,每个用户在服务器端保存两个属性:用户名usr和用户密码pas*/
{char usr[20];
char pas[20];
}usr[USRNUM]={
{"lwy","111"},
{"abc","123"},
{"efg","456"},
};
static char Dir[20];/*保存用户名*/
static char Filen[20];/*保存用户文件的文件名*/
int main()
{
int sockfd,conn_fd ; /*sockfd:监听socket,conn_fd:数据传输socket,即发送数据用的套接字标识符*/
char buf[MAXDATASIZE];/*缓冲区大小*/
struct sockaddr_in my_addr; /*本机地址信息*/
struct sockaddr_in their_addr; /*客户机地址信息*/
int sin_size; /*客户机地址长度*/
struct usr_pas *upp; /*为即将登陆服务器的用户创建用户结构*/
upp=&usr[0];
printf("Server strat\n");
sockfd = socket(AF_INET, SOCK_STREAM, 0); /*建立套接字*/
if (sockfd == -1)
{
printf("SOCKET ERROR!!!\n");
exit(1);
}
/*填充服务器地址结构*/
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(PORT);
my_addr.sin_addr.s_addr=INADDR_ANY;
bzero(&(my_addr.sin_zero),8); /*将填充区域填0*/
/*套接字与本机地址绑定*/
if(bind(sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))==-1)
{
printf("BIND ERROR!!!\n");
exit(1);
}
if(listen(sockfd,BACKLOG)==-1) /*服务器建立监听*/
{
printf("LISTEN ERROR!!!\n");
exit(1);
}
/*************************************/
while(1)
{ /*循环处理客户机请求*/
sin_size=sizeof(struct sockaddr_in);
/*响应请求,建立新的套接字*/
conn_fd=accept(sockfd, (struct sockaddr *)&their_addr,&sin_size);
if(conn_fd==-1)
{
printf("ACCEPT ERROR!!!\n");
continue;
}
printf("Server: got connection from %s\n",inet_ntoa(their_addr.sin_addr)); /*客户端与服务器连接成功*/
if(!fork()) /*调用fork()创建子进程*/
{
char cdir[20];
char str[40]="mkdir ";
upp=&usr[0];
login_m(conn_fd,&buf,upp); /*用户登陆,服务器验证其身份是否合法*/
strcpy(cdir,Dir); /*用户登录成功后,用户名将存入Dir中保存*/
strcat(str,cdir); /*为用户创建属于他自己的目录,目录名为该用户的用户名*/
printf("%s\n",cdir);
printf("%s\n",Filen);
if(!system(str))
printf("mkdir %s ok\n",cdir);
else
printf("mkdir %s faile!\n",cdir);
while(1)
{
S_exe(conn_fd,&buf,cdir); /*响应用户各种请求*/
}
close(conn_fd); /*关闭新套接字*/
exit(0);
}
close(conn_fd); /*关闭套接字*/
while(waitpid(-1,NULL,WNOHANG)>0);
}
}
/*login函数,进行用户身份的验证*/
login_m(int conn_fd,char * buf,struct usr_pas *upp)
{
int u=0,p=0;
int i;
char usr[20];
char pas[20];
send(conn_fd,"Please Enter your username:",28,0); /*使用套接字向用户发送数据,服务器向用户提示输入User name:*/
recv(conn_fd,buf,MAXDATASIZE,0); /*使用套接字接受用户返回的信息,即接受用户输入的User name*/
strncpy(usr,buf,20); /*将读到的用户名放usr中保存*/
send(conn_fd,"Please Enter your password:",28,0); /*继续使用套接字向用户发送数据,服务器向用户提示输入password*/
recv(conn_fd,buf,MAXDATASIZE,0); /*使用套接字接受用户返回的信息,即接受用户输入的password*/
strncpy(pas,buf,20); /*将读到的用户密码放pas中保存*/
for(i=0,u=0,p=0;i<USRNUM;i++,upp++) /*测试三次,察看用户输入的user name和password是否与服务器中已经存储的三个用户之一相符;此处用upp遍历服务器中已经保存的用户*/
{
if(strcmp(usr,upp->usr)==0)
{
u=1;
printf("user name is:%s\n",usr);
}
if(strcmp(pas,upp->pas)==0)
{
p=1;
printf("password is:%s\n",pas);
}
if((u==1&&p==1)) /*user name 和password都输入正确,则将用户名放Dir中保存,为接下来为用户创建专署目录做准备*/
{
printf("user connect\n");
strcpy(Dir,usr);
return 0;
}
if((u==1&&p!=1)) /*用户名输入正确,但是password有误,关闭套接字,服务器断开与客户端的通信*/
{
send(conn_fd,"connect stop! Wrong password\n",30,0);
printf("wrong password!drop user!\n");
close(conn_fd);
exit(0);
}
}
send(conn_fd,"connect stop!\n",15,0); /*输入的user name在服务器里找不到相应的记录,则用户登录失败*/
printf("user fail to connect to server!\n");
close(conn_fd); /*关闭新套接字*/
exit(0);
}
/*S_exe函数,完成用户请求的各种功能*/
S_exe(int conn_fd,char * buf,char *cdir)
{
char filename[20];
send(conn_fd,">",2,0); /*服务器提示用户可继续操作*/
printf("Send: >\n");
recv(conn_fd,buf,MAXDATASIZE,0); /*接受用户接下来的请求*/
printf("Client: %s\n",buf);
if(strcmp(buf,"put")==0) /*接收到put*/
{
S_put(conn_fd,buf,cdir);
}
if(strcmp(buf,"query")==0) /*接收到query*/
{
S_query(conn_fd,buf,cdir);
}
if(strcmp(buf,"result")==0) /*接收到result*/
{
S_result(conn_fd,buf,cdir);
}
if(strcmp(buf,"ls")==0) /*接收到ls*/
{
S_ls(conn_fd,buf,cdir);
}
/*接收到中止连接命令bye,服务器将断开与用户的连接*/
if(strcmp(buf,"bye")==0)
{
send(conn_fd,"connect stop!\n",15,0);
printf("user exit\n");
close(conn_fd);
exit(0);
}
sleep(1);
}
/*S_put函数,将用户指定的文件放到用户所属的文件夹目录下*/
S_put(int conn_fd,char * buf)
{
FILE *fp;
char filename[20];
char str[30];
char path[30];
long int size;
recv(conn_fd,filename,20,0); /*接受客户端发送的文件名*/
if(strncmp(filename,"!error!",7)==0)
{
printf("user transport error!\n");
return 0;
}
strcpy(Filen,"");
strcat(Filen,filename);/*服务器接受用户传来的文件名后,保存在Filen里*/
printf("%s\n",Filen);
strcpy(path,""); /*path将保存文件的完整路径*/
strcat(path,Dir); /*usr/filename*/
strcat(path,"/");
strcat(path,filename);
printf("create file: %s\n",path); /*显示该文件现在存放的路径*/
if((fp=fopen(path,"wb"))==NULL) /*打开文件,准备开始读取文件的内容*/
{
printf("creat file faile!\n");
send(conn_fd,"!error!",8,0);
exit(0);
}
send(conn_fd,"transport ready",16,0);
size=read(conn_fd,buf,MAXDATASIZE); /*size保存文件内容的大小*/
/*显示文件的内容*/
while((strcmp(buf,"!file! !end!"))!=0)
{
fwrite(buf,size,1,fp);
size=read(conn_fd,buf,MAXDATASIZE);
}
printf("file transprots OK\n");
fclose(fp);
}
/************************S_compile函数**********************************/
S_compile(int conn_fd,char * buf,char * dir)
{
char filename[20];
char str[30];
FILE *fp;
printf("Compiling with ");
strcat(str,"gcc ");/*gcc编译文件*/
strcat(str,Dir);
strcat(str,"/");
strcat(str,Filen);
printf("%s\n",str);
if(!system(str))
{
printf("Compile OK!");
strcat(str,"");
strcat(str,"./"); /*运行文件*/
strcat(str,Dir);
strcat(str,"/");
strcat(str,"a.out ");
strcat(str,">");
strcat(str,"result");/*./qiao/a.out >result*/
printf("Write result: %s\n",str);
if(!system(str))
{
printf("state is run over\n");
if((fp=fopen("result","rb"))==NULL)
{
printf("result can not view\n");
send(conn_fd,"State run error!\n",18,0);
return 0;
}
send (conn_f