客户端
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/un.h>
#include <sys/epoll.h>
typedef struct sockaddr_in addr_in_t;
typedef struct sockaddr addr_t;
typedef struct sockaddr_un addr_un_t;
int find_name(const char* name);
enum Type
{
TYPE_REGIST,
TYPE_LOGIN,
TYPE_CHAR,
TYPE_FILE_OUT
};
typedef struct pack_t{
enum Type type;
char name[20];
char pswd[20];
char filename[64];
long filesize;
char ownname[20];
char text[1024];
}pack_t;
typedef struct user_t{
char user_name[20];
char user_pswd[20];
int user_sock_fd;
int flagMsg;
char Msg[1024];
int flagFile;
char fname[64]; //文件在服务器的文件名地址
char file_name[64];//源文件名
}user_t;
user_t user[50] = {0};
int len = 0;
void add_name(user_t own);
void read_data(int client);
int main(int argc, const char *argv[])
{
if(argc < 2)
{
printf("请输入端口号\n");
return -1;
}
int port = atoi(argv[1]);
int server_fd = socket(AF_INET,SOCK_STREAM,0);//创造服务器套接字
addr_in_t addr = {0};
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr("0.0.0.0");
if(bind(server_fd,(addr_t*)&addr,sizeof(addr)) == -1)//将要接受信息的IP和port写入服务器套接字,并判断是否写入成功
{
perror("bind");
return -1;
}
listen(server_fd,10);//监听,创造监听列表,将监听到的客户端存入监听列表中
int epfd = epoll_create1(EPOLL_CLOEXEC); //创造一个动态的监视列表,并返回该列表的文件描述符
struct epoll_event server_event = {.events=EPOLLIN,.data.fd=server_fd};
epoll_ctl(epfd,EPOLL_CTL_ADD,server_fd,&server_event); //将服务器套接字描述符以监视是否可读的形式写入监视列表
struct epoll_event stdin_event = {.events=EPOLLIN,.data.fd=0};
epoll_ctl(epfd,EPOLL_CTL_ADD,0,&stdin_event);//将标准输入流的描述符写入监听列表
struct epoll_event arr[64] = {0}; //创造一个用来保存已被激活的描述符
while(1)
{
int size = epoll_wait(epfd,arr,64,-1); //监视有多少个描述符被激活,接收被激活的个数,并将激活的描述符存入到arr结构体数组中
for(int i=0;i<size;i++)
{
if(arr[i].events != EPOLLIN) //如果该描述符不是以可读的形式被激活的,那么久跳出当前循环
{
continue;
}
int fd = arr[i].data.fd;
if(fd == server_fd) //有客户端连接服务器
{
int client_fd = accept(server_fd,0,0); //接收客户端的连接并返回该客户端套接字在服务器中的描述符
printf("有客户端连接\n");
struct epoll_event client_event = {.events=EPOLLIN,.data.fd=client_fd};
epoll_ctl(epfd,EPOLL_CTL_ADD,client_fd,&client_event); //将接收到的客户端套接字的描述符存入到监视列表中
}
else if(fd == 0) //标准输入流有可读取的内容(键盘敲入数据)
{
char buf[64] = "";
scanf("%s",buf); //读取标准输入流的数据
while(getchar()!=10); //吸收在缓存区多余的数据
printf("标准输入流的数据为:%s\n",buf);
}
else //客户端有发来数据
{
read_data(fd);
}
}
}
return 0;
}
int find_name(const char* name)
{
for(int i=0; i<len; i++)
{
if(strcmp(name,user[i].user_name) == 0)
{
return i;
}
}
return -1;
}
void add_name(user_t own)
{
user[len] = own;
len++;
}
void read_data(int client)
{
pack_t pack = {0};
int res = read(client,&pack,sizeof(pack));
switch(pack.type)
{
case TYPE_REGIST:
{
char* msg = NULL;
int flag = find_name(pack.name);
if(flag == -1)
{
user_t own = {0};
strcpy(own.user_name,pack.name);
strcpy(own.user_pswd,pack.pswd);
add_name(own);
msg = "创建成功";
}
else
{
msg = "创建失败\n";
}
strcpy(pack.text,msg);
write(client,&pack,sizeof(pack));
break;
}
case TYPE_LOGIN:
{
char* msg = NULL;
int flag = find_name(pack.name);
if(flag == -1)
{
msg = "没有此用户";
}
else
{
user_t user1 = user[flag];
if(strcmp(user1.user_pswd,pack.pswd) == 0)
{
msg = "登录成功";
user[flag].user_sock_fd = client;
if(user[flag].flagMsg == 1)
{
pack_t pack = {0};
pack.type = TYPE_CHAR;
strcpy(pack.text,user[flag].Msg);
write(client,&pack,sizeof(pack));
user[flag].flagMsg = 0;
}
if(user[flag].flagFile == 1)
{
pack_t pack = {0};
pack.type = TYPE_FILE_OUT;
int fd = open(user[flag].fname,O_RDONLY);
struct stat stat_buf = {0};
stat(user[flag].fname,&stat_buf);
long len = stat_buf.st_size;
strcpy(pack.filename,user[flag].file_name);
pack.filesize=len;
write(client,&pack,sizeof(pack));
long read_size = 0;
while(1)
{
memset(pack.text,0,sizeof(pack.text));
read(fd,&pack,sizeof(pack));
int read = strlen(pack.text);
read_size += read;
write(client,&pack,sizeof(pack));
if(read_size >= len)
{
break;
}
}
close(fd);
user[flag].flagFile == 0;
}
}
else
{
msg = "密码错误";
}
}
strcpy(pack.text,msg);
write(client,&pack,sizeof(pack));
break;
}
case TYPE_CHAR:
{
char* msg = NULL;
int flag = find_name(pack.ownname);
if(flag == -1)
{
msg = "没有此用户";
}
else
{
int sock = user[flag].user_sock_fd;
if(sock == 0)
{
msg = "该用户没登录";
user[flag].flagMsg = 1;
strcpy(user[flag].Msg,pack.text);
}
else
{
write(sock,&pack,sizeof(pack));
msg = "发送成功";
}
}
strcpy(pack.text,msg);
write(client,&pack,sizeof(pack));
break;
}
case TYPE_FILE_OUT:
{
char* msg = NULL;
int flag = find_name(pack.ownname);
if(flag == -1)
{
msg = "没有该用户";
}
else
{
if(user[flag].user_sock_fd == 0)
{
msg = "该用户处于离线状态";
strcpy(user[flag].file_name,pack.filename);
char filename[64] = "./server/" ;
strcpy(filename,pack.filename);
strcpy(user[flag].fname,filename);
user[flag].flagFile = 1;
int fd = open(filename,O_WRONLY|O_CREAT|O_TRUNC,0664);
long len = pack.filesize;
long readed_size = 0;
while(1)
{
memset(pack.text,0,sizeof(pack.text));
read(client,&pack,sizeof(pack));
printf("消息存入本地中\n");
int read = strlen(pack.text);
write(fd,pack.text,read);
readed_size += read;
if(readed_size >= len)
{
break;
}
}
close(fd);
}
else
{
while(1)
{
printf("服务器接收中\n");
read(user[flag].user_sock_fd,&pack,sizeof(pack));
}
}
}
}
}
}
客户端
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/un.h>
typedef struct sockaddr_in addr_in_t;
typedef struct sockaddr addr_t;
typedef struct sockaddr_un addr_un_t;
enum Type
{
TYPE_REGIST,
TYPE_LOGIN,
TYPE_CHAR,
TYPE_FILE_OUT
};
typedef struct pack_t{
enum Type type;
char name[20];
char pswd[20];
char filename[64];
long filesize;
char ownname[20];
char text[1024];
}pack_t;
void* thread_main(void* arg){
int client =*(int*)arg;
while(1){
pack_t pack ={0};
int res = read(client,&pack,sizeof(pack));
if(res ==0){break;}
switch(pack.type){
case TYPE_REGIST:
printf("%s\n",pack.text);
break;
case TYPE_LOGIN:
printf("%s\n",pack.text);
break;
case TYPE_CHAR:
printf("%s\n",pack.text);
break;
case TYPE_FILE_OUT:
{
char filename[64] = "./client/" ;
strcpy(filename,pack.filename);
long len = pack.filesize;
int fd = open(filename,O_WRONLY|O_CREAT|O_TRUNC,0664);
long read_size = 0;
while(1)
{
memset(pack.text,0,sizeof(pack.text));
read(client,&pack,sizeof(pack));
int read = strlen(pack.text);
read_size += read;
write(fd,pack.text,strlen(pack.text));
printf("接收中\n");
if(read_size >= len)
{
break;
}
}
close(fd);
}
}
}
}
int main(int argc, const char *argv[])
{
if(argc !=2 ){
printf("请输入端口号\n");
return 1;
}
// ./server 8888
int port = atoi(argv[1]);// 将字符串 8888 转换成int类型port
int client = socket(AF_INET,SOCK_STREAM,0);
addr_in_t addr = {0};
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr("192.168.127.129");
if(connect(client,(addr_t*)&addr,sizeof(addr)) == -1){
perror("connect");
return 1;
}
pthread_t id;
pthread_create(&id,0,thread_main,&client);
pthread_detach(id);
while(1)
{
int flag;
printf("1.注册\n");
printf("2.登录\n");
printf("3.发送消息\n");
printf("4.发送文件\n");
printf("5.退出\n");
printf("请输入:");
scanf("%d",&flag);
switch(flag)
{
case 1:
{
pack_t pack = {0};
pack.type = TYPE_REGIST;
printf("请输入新账号:");
scanf("%s",pack.name);
printf("请输入密码:");
scanf("%s",pack.pswd);
write(client,&pack,sizeof(pack));
break;
}
case 2:
{
pack_t pack = {0};
pack.type = TYPE_LOGIN;
printf("请输入账号:");
scanf("%s",pack.name);
printf("请输入密码:");
scanf("%s",pack.pswd);
write(client,&pack,sizeof(pack));
break;
}
case 3:
{
pack_t pack = {0};
pack.type = TYPE_CHAR;
printf("请输入被发送人账号以及内容\n");
scanf("%s %s",pack.ownname,pack.text);
write(client,&pack,sizeof(pack));
break;
}
case 4:
{
pack_t pack = {0};
pack.type = TYPE_FILE_OUT;
printf("请输入被发送人的账号:");
scanf("%s",pack.ownname);
while(getchar()!= 10);
printf("请输入文件名:");
scanf("%s",pack.filename);
int fd = open(pack.filename,O_RDONLY);
if(fd == -1)
{
printf("没有该文件\n");
return -1;
}
struct stat stat_buf = {0};
stat(pack.filename,&stat_buf);
pack.filesize = stat_buf.st_size;
write(client,&pack,sizeof(pack));
long readed_size = 0;
while(1)
{
memset(pack.text,0,sizeof(pack.text));
read(fd,&pack,sizeof(pack));
int read = strlen(pack.text);
write(client,&pack,sizeof(pack));
printf("文件传输中\n");
if(readed_size >= pack.filesize)
{
break;
}
}
}
case 5:exit(0);
}
}
return 0;
}