开发环境:deepin 15.10桌面版,GCC版本7.3.0
代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define true 1
#define false 0
#define MAXSIZE 2048
#define NAMELENTH 20
#define PORT 2999
#define BACKLOG 8
#define MAXTHREAD 8
struct info
{
pthread_t thread_id;//当前线程id
int index;//当前clients数组下表
int connectfd; //当前连接套接字
};
unsigned int thread_num=0;//用于记录线程数量,当thread_num==MAXTHREAD就应该让新接入的客户端等待了。
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; //线程互斥锁初始化,不确定可用。
struct info clients[MAXTHREAD]={0};//保存客户端信息的数组,线程函数中会传入下标,在线程函数中应该使用传入的cur_index而不是thread_num
int useable[MAXTHREAD];//记录可用的clients下标,创建线程之后将相应下标置0,在线程执行完毕之后应将相应的下标置1;
void* client_in(void* cur_index); //线程函数,参数为当前的线程下标,用于不同线程间的区分。
void take_order(char* cmd,int cur_index);//执行具体命令,为了方便操作,且因为线程间问题,在执行文件传输中直接对cliens下标进行操作
void send_msg(const char* msg,int index);//发送消息
void send_dir(int index);//发送当前目录内容
void recive_msg(int index);//接收消息
void recive_cmd(char* cmd_buf,int index);//接收命令
int recive_choice(int index);//接收选择
void send_file(char* filename,int index);//发送文件
void recive_file(char* filename,int index);//接收文件
int main()
{
memset(useable,1,sizeof(useable));
struct sockaddr_in saddr;
int listenfd=socket(AF_INET,SOCK_STREAM,0);
if(listenfd<0)
{
perror("socket");
exit(-1);
}
int opt=SO_REUSEADDR;
memset(&saddr,0,sizeof(saddr));
saddr.sin_addr.s_addr=htons(INADDR_ANY);
saddr.sin_family=AF_INET;
saddr.sin_port=htons(PORT);
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
if(bind(listenfd,(struct sockaddr*)&saddr,sizeof(struct sockaddr_in))<0)
{
perror("bind");
exit(-1);
}
if((listen(listenfd,BACKLOG))<0)
{
perror("listen");
exit(-1);
}
printf("------------------------------------------------\n");
printf(" |server started, waiting for clients conncet|\n");
printf("------------------------------------------------\n");
while(1)
{
struct sockaddr_in caddr;
memset(&caddr,0,sizeof(caddr));
int n= sizeof(caddr);
int fd=accept(listenfd,(struct sockaddr*)&caddr,&n);
if(fd<0)
{perror("connect");exit(-1);}
printf("client has connected:%s",inet_ntoa(caddr.sin_addr));
if(thread_num<=MAXTHREAD)
{
int index;
for(index=0;index<MAXTHREAD;index++)
{
if(useable[index])
break;
}
send_msg("\0",index);
int num=pthread_create(&(clients[index].thread_id),NULL,&client_in,&index);
if(num<0)
{
printf("thread create fail!");
exit(-1);
}
clients[index].connectfd=fd;
clients[index].index=index;
useable[index]=0;
thread_num++;
}
else
{
printf("there is one client be hold!");
//send(fd,"server is busy now ,retry later",MAXSIZE,0);//线程队列满,向客户端发送消息。
}
}
close(listenfd);
return 0;
}
void* client_in(void* cur_index)
{
int is_continue=1;
int index=*((int*)cur_index);
char * cmd=(char*)malloc(MAXSIZE);
send_msg("Hello!you has been connected with our server\nNow you can input your order:\n",index);
while(is_continue)
{
recive_cmd(cmd,index);
send_msg("recive your command, try to analyze....\n",index);
take_order(cmd,index);
send_msg("Wanna take another order?[Y/N]?\n",index);
memset(cmd,0,MAXSIZE);
is_continue=recive_choice(index);
if(is_continue<0)
{
send_msg("wrong choice",index);
break;
}
}
close(clients[index].connectfd);
useable[clients[index].index]=1;
return ;
}
void take_order(char* cmd,int index)
{
if(strncmp(cmd,"exit",4)==0)
{
pthread_cancel(clients[index].thread_id);
}
else if(strncmp(cmd,"ls",2)==0)
{
send_dir(index);
}
else if(strncmp(cmd,"get",3)==0)
{
char filename[MAXSIZE];
memset(filename,0,MAXSIZE);
strcat(filename,cmd+4);
send_file(filename,index);
}
else if(strncmp(cmd,"put",4)==0)
{
char filename[MAXSIZE];
memset(filename,0,MAXSIZE);
strcat(filename,cmd+4);
recive_file(filename,index);
}
else
{
send_msg("missing order!\n",index);
}
}
void send_msg(const char* msg,int index)
{
if(send(clients[index].connectfd,msg,MAXSIZE,0)<0)
perror("send");
}
void send_dir(int index)
{
int fd;
int bakfd=dup(1);
close(1);
dup(fd);
system("ls .");
char buf[MAXSIZE];
memset(buf,0,MAXSIZE);
do
{
if(read(fd,buf,MAXSIZE)<0) perror("read");
send_msg(buf,index);
}
while(buf[MAXSIZE-1]=='\0');
close(fd);
dup(bakfd);
}
void recive_msg(int index)
{
char buf[MAXSIZE];
do
{
memset(buf,0,MAXSIZE);
if(recv(clients[index].connectfd,buf,MAXSIZE,0)<0)
perror("recv");
printf("%s",buf);
}
while(buf[MAXSIZE]=='\0');
}
void recive_cmd(char* cmd_buf,int index)
{
memset(cmd_buf,0,MAXSIZE);
if(recv(clients[index].connectfd,cmd_buf,MAXSIZE,0)<0)
perror("recv");
printf("recive commands:[%s]",cmd_buf);
}
int recive_choice(int index)
{
char buf[MAXSIZE];
memset(buf,0,MAXSIZE);
if(recv(clients[index].connectfd,buf,MAXSIZE,0)<0)
perror("recv");
if(!strncmp("Y",buf,1)||!strncmp("y",buf,1))
return true;
else if(!strncmp("N",buf,1)||!strncmp("n",buf,1))
return false;
else
return -1;
}
void send_file(char* filename,int index)
{
char buf[MAXSIZE];
int fd= open(filename,O_RDONLY);
if(fd<0)
perror("open");
do
{
memset(buf,0,MAXSIZE);
if(read(fd,buf,MAXSIZE)<0) perror("read");
if(send(clients[index].connectfd,buf,MAXSIZE,0)<0) perror("send");
}
while(buf[MAXSIZE-1]=='\0');
}
void recive_file(char*filename,int index)
{
printf("restore file :%s",filename);
char buf[MAXSIZE];
int fd=open(filename,O_RDWR|O_CREAT);
if(fd<0) perror("open");
do
{
memset(buf,0,MAXSIZE);
if(recv(clients[index].connectfd,buf,MAXSIZE,0)<0) perror("recv");
if(write(fd,buf,MAXSIZE)<0) perror("write");
lseek(fd,MAXSIZE,SEEK_SET);
}
while(buf[MAXSIZE-1]=='\0');
}
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXSIZE 2048
#define PORT 2999
int sockfd=-1;
void recive_msg()//接受消息
{
char buf[MAXSIZE];
do
{
memset(buf,0,MAXSIZE);
if(recv(sockfd,buf,MAXSIZE,0)<0)
perror("recv");
printf("%s",buf);
} while (buf[MAXSIZE-1]=='\0');
};
void recive_file(char *filename)//接受文件
{
printf("restore file with name : %s",filename);
char buf[MAXSIZE];
int fd = open(filename,O_RDWR|O_CREAT);
if(fd<0)
perror("open");
do
{
memset(buf,0,MAXSIZE);
if(recv(sockfd,buf,MAXSIZE,0)<0)
perror("recv");
if(write(fd,buf,MAXSIZE)<0)
perror("write");
lseek(fd,MAXSIZE,SEEK_SET);
}
while(buf[MAXSIZE-1]=='\0');
}
void send_msg(const char* msg)//发送消息
{
if(send(sockfd,msg,MAXSIZE,0)<0)
perror("send");
}
void send_file(char* filename)//发送文件
{
printf("send %s to server",filename);
int fd= open(filename,O_RDONLY);
if(fd<0)
{perror("open");exit(-1);}
char buf[MAXSIZE];
do
{
memset(buf,0,MAXSIZE);
if(read(fd,buf,MAXSIZE)<0)
perror("read");
if(send(sockfd,buf,MAXSIZE,0)<0)
perror("send");
}
while(buf[MAXSIZE-1]=='\0');
}
void send_order(char * cmd)
{
if(strncmp(cmd,"exit",4)==0)
{
send_msg(cmd);
}
else if(strncmp(cmd,"ls",2)==0)
{
send_msg(cmd);
}
else if(strncmp(cmd,"get",3)==0)
{
char filename[MAXSIZE];
memset(filename,0,MAXSIZE);
strcat(filename,cmd+4);
recive_file(filename);
}
else if(strncmp(cmd,"put",4)==0)
{
char filename[MAXSIZE];
memset(filename,0,MAXSIZE);
strcat(filename,cmd+4);
send_file(filename);
}
}
int main()
{
fflush(stdin);
char * buf=(char*)malloc(MAXSIZE);
memset(buf,0,MAXSIZE);
printf("Try to login server,please input the address of server:");
scanf("%s",buf);
sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd<0){perror("socket");exit(-1);}
struct sockaddr_in saddr;
struct hostent * host;
if((host=gethostbyname(buf))==NULL)
{
printf("name solution fail\n");
exit(-1);
}
memset(&saddr,0,sizeof(saddr));
saddr.sin_addr=*((struct in_addr *)host->h_addr_list[0]);
saddr.sin_family=AF_INET;
saddr.sin_port=htons(PORT);
if(connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr))<0)
{
perror("connect");exit(-1);
}
while(1)
{
memset(buf,0,MAXSIZE);
recv(sockfd,buf,MAXSIZE,0);
if(buf[0]!='\0')
{
printf("%s",buf);
}
else break;
}
memset(buf,0,MAXSIZE);
while(1)
{
recive_msg();
memset(buf,0,MAXSIZE);
fflush(stdin);
fgets(buf,MAXSIZE,stdin);
buf[strlen(buf)-1]='\0';
send_order(buf);
}
}
编译通过后,首先运行服务端程序,出现文字提示后运行客户端程序,输入服务端ip地址,若运行成功则可以输入命令:
ls(列出文件)
put(上传文件)
get(下载文件)
exit (退出链接)