传文件
本质:客户端通过标准IO或者文件IO,读取文件中的信息
然后将读取到的信息,通过套接字发送给服务器
服务器接收到后,立刻通过标准IO或者文件IO写到文件
这个过程,服务器要知道2件事
1:客户端发来的文件名字
2:客户端发来的文件大小(stat函数获取)
sever.c
typedef struct Pack{
char filename[64];
long filesize;
}pack_t;
void read_file(int client);
int main(int argc, const char *argv[])
{
if(argc<2){
printf("输入port\n");
return 1;
}
int port=atoi(argv[1]);
int server=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");
bind(server,(addr_t*)&addr,sizeof(addr));
listen(server,10);
int epfd=epoll_create1(EPOLL_CLOEXEC);
struct epoll_event epoll_stdin={.events=EPOLLIN,.data.fd=0};
struct epoll_event epoll_server={.events=EPOLLIN,.data.fd=server};
epoll_ctl(epfd,EPOLL_CTL_ADD,0,&epoll_stdin);
epoll_ctl(epfd,EPOLL_CTL_ADD,server,&epoll_server);
struct epoll_event arr[50]={0};
while(1){
int len=epoll_wait(epfd,arr,50,-1);
for(int i=0;i<len;i++){
int fd=arr[i].data.fd;
if(fd==server){
int client=accept(server,0,0);
printf("weclome新客户%d\n",client);
struct epoll_event epoll_client={.events=EPOLLIN,.data.fd=client};
epoll_ctl(epfd,EPOLL_CTL_ADD,client,&epoll_client);
}
else if(fd==0){
char buf[64];
scanf("%63s",buf);
while(getchar()!=10);
printf("stdin:%s\n",buf);
}else{/*
char buf[64];
int res=read(fd,buf,64);
if(0==res){
printf("%d客户断开连接\n",fd);
epoll_ctl(epfd,EPOLL_CTL_DEL,fd,0);
close(fd);
}else
printf("%d消息:%s\n",fd,buf);
*/
read_file(fd);
}
}
}
return 0;
}
void read_file(int client){
pack_t pack;
read(client,&pack,sizeof(pack));//先收pack (才能打开文件)
long filesize=pack.filesize;
char filename[64]="server_file_system/";
strcat(filename,pack.filename);
int fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC,0666);
long read_size=0;
while(1){
char buf[1024];
int res=read(client,buf,1024);//再收file内容
read_size+=res;
if(read_size>=filesize){
printf("文件内容传输完毕\n");
break;
}
write(fd,buf,res);
}
close(fd);
}
client.c
typedef struct Pack{
char filename[64];
long filesize;
}pack_t;
int main(int argc, const char *argv[])
{
if(argc<2){
printf("port\n");
return 1;
}
int port =atoi(argv[1]);
int client=socket(AF_INET,SOCK_STREAM,0);
addr_in_t add;
add.sin_family=AF_INET;
add.sin_port=htons(port);
add.sin_addr.s_addr=inet_addr("192.168..");
connect(client,(addr_t*)&add,sizeof(add));
while(1){
pack_t pack;
printf("filename:\n");
scanf("%63s",pack.filename);
while(getchar()!=10);
int fd=open(pack.filename,O_RDONLY,0666);
struct stat s;
stat(pack.filename,&s);
pack.filesize=s.st_size;
printf("filesize=%ld B\n",pack.filesize);
write(client,&pack,sizeof(pack));//先传pack
while(1){
char buf[1024];
int res=read(fd,buf,1024);//
write(client,buf,res);//再传file内容
if(0==res)break;
}
close(fd);
}/*
while(1){
char buf[64];
printf("scanf:buf\n");
scanf("%s",buf);
while(getchar()!=10);
write(client,buf,64);
}*/
return 0;
}
传数据
server.c
enum Type{
TYPE_REGIST,
TYPE_LOGIN,
TYPE_CHAT
};
typedef struct Pack{
enum Type type;
char name[20];
char pswd[20];
char tarname[20];
char text[1024];
} pack_t;
typedef struct User{
char name[20];
char pswd[20];
//int hasmsg;
//char msge[1024];
int sock;
} user_t;
user_t user_arr[50] = {0};
int user_len = 0;
void insert_user(user_t user);
int find_user(const char* username);
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 = 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");
bind(server,(addr_t*)&addr,sizeof(addr));
listen(server,10);
int epfd = epoll_create1(EPOLL_CLOEXEC);
struct epoll_event epoll_stdin = {.events = EPOLLIN,.data.fd = 0};
struct epoll_event epoll_server ={.events = EPOLLIN,.data.fd = server};
epoll_ctl(epfd, EPOLL_CTL_ADD, 0, &epoll_stdin);
epoll_ctl(epfd, EPOLL_CTL_ADD, server, &epoll_server);
struct epoll_event arr[50] = {0};
while(1){
int len = epoll_wait(epfd, arr, 50, -1); // 等待事件发生
for(int i=0; i<len; i++){
int fd = arr[i].data.fd; // 获取触发事件的文件描述符
if(fd == server){ //服务端socket有新连接
int client = accept(server, 0, 0);
printf("%d客户端连接\n",client);
struct epoll_event epoll_client = {.events = EPOLLIN,.data.fd = client};
epoll_ctl(epfd, EPOLL_CTL_ADD, client, &epoll_client);
} else if(fd == 0){ // 标准输入
char buf[64];
scanf("%63s", buf);
while(getchar() != '\n');
printf("键盘输入数据:%s\n", buf);
} else{ // 客户端发送的数据
read_data(fd);// 处理文件或网络数据的读取
}
}
}
return 0;
}
void insert_user(user_t user){
user_arr[user_len] = user;
user_len++;
}
int find_user(const char* username){
for(int i=0;i<user_len;i++)
if(strcmp(username,user_arr[i].name) == 0)
return i;
return -1;
}
void read_data(int client){
//while(1){
pack_t pack ;
read(client,&pack,sizeof(pack));///
int res = find_user(pack.name);// 根据用户发来的账号,在数组中查询是否存在
char* msg = NULL;
switch(pack.type){
case TYPE_REGIST:{
if(res == -1){// 不存在
user_t user;
strcpy(user.name,pack.name);
strcpy(user.pswd,pack.pswd);
insert_user(user);
msg = "注册成功";
}else
msg = "该账号已存在";
strcpy(pack.text,msg);
write(client,&pack,sizeof(pack));///
break;
}
case TYPE_LOGIN:{
if(res == -1)
msg = "该账号不存在";
else{
user_t user = user_arr[res];// 将找到的用户单独拎出来
if(strcmp(user.pswd,pack.pswd) == 0){
msg = "登录成功";
user_arr[res].sock = client;
/*
if(user_arr[res].hasmsg){
pack_t pack={0};
pack.type=TYPE_CHAT;
strcpy(pack.text,user_arr[res].msge);
write(client,&pack,sizeof(pack));///
user_arr[res].hasmsg=0;
}*/
}else
msg =" 密码错误";
}
strcpy(pack.text,msg);
write(client,&pack,sizeof(pack)); ///
break;
}
case TYPE_CHAT:{
if(res == -1){
msg = "用户不存在";
strcpy(pack.text, msg);
write(client, &pack, sizeof(pack));///
}else{
user_t user = user_arr[res];
if(user.sock == 0){
msg = "用户未登录";
/*user_arr[res].hasmsg=1;
strcpy(user_arr[res].msge,pack.text);*/
strcpy(pack.text, msg);
write(client, &pack, sizeof(pack));///
}else{// 用户登录
int tarsock = user.sock;
write(tarsock, &pack, sizeof(pack));///
}
}
break;
}
}
}
client.c
enum Type{
TYPE_REGIST,
TYPE_LOGIN,
TYPE_CHAT
};
typedef struct Pack{
enum Type type;
char name[20];
char pswd[20];
char tarname[20];
char text[1024];
}pack_t;
void* thread_main(void* arg){//后台read(client)
int client = *(int*)arg;
while(1){
pack_t pack = {0};
int res = read(client,&pack,sizeof(pack));///r
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_CHAT:
printf("接收到消息:%s\n",pack.text);
break;
}
}
}
int main(int argc, const char *argv[]){//前台write(client)
if(argc != 2){
printf("请输入端口号\n");
return 1;
}
int port = atoi(argv[1]);
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..");
connect(client,(addr_t*)&addr,sizeof(addr));
pthread_t id;
pthread_create(&id, 0, thread_main, &client);
pthread_detach(id);
while (1) {
int ch = -1;
printf("1:注册\n");
printf("2:登录\n");
printf("3:聊天\n");
printf("0:退出\n");
printf("请选择:");
scanf("%d", &ch);
while (getchar() != 10);
pack_t pack;
switch (ch) {
case 1:
pack.type = TYPE_REGIST;
printf("请输入账号:");
scanf("%s", pack.name);
while (getchar() != 10);
printf("请输入密码:");
scanf("%s", pack.pswd);
while (getchar() != 10);
write(client, &pack, sizeof(pack));///w
break;
case 2:
pack.type = TYPE_LOGIN;
printf("请输入账号:");
scanf("%s", pack.name);
while (getchar() != 10);
printf("请输入密码:");
scanf("%s", pack.pswd);
while (getchar() != 10);
write(client, &pack, sizeof(pack));///w
break;
case 3:
// 聊天对象的姓名放在pack.tarname里面
// 聊天内容放在 pack.text 里面
// 例如:张三 你好
pack.type = TYPE_CHAT;
scanf("%s %s", pack.tarname, pack.text);
while(getchar() != '\n');
//printf("tarname = %s\n", pack.tarname);
write(client, &pack, sizeof(pack));///w
break;
case 0:
break;
}
}
}