基于Linux的客户端与服务端的传输和信息交互,利用socket网络来构建服务端和客户端的网络请求,在服务端接收到客户端的连接请求的时候创建进程用于,服务端与多个客户端之间的连接,在头文件中穿件用于网络传输数据的结构体,其中包括具体的命令(cmd),传输文件时文件中的内容(context),以及用于判断在传输后是否需要创建文件的标志位;利用字符串处理函数来分解指令,获得具体指令,再根据指令的类型来选择需要执行的代码,实现服务端与客户端之间的文件传输和信息交互;
头文件中包含宏定义各个指定,和数据传输过程中的结构体: parament.h
#define LS 1
#define CD 2
#define PWD 3
#define LLS 4
#define LCD 5
#define DOWNLOAD 6
#define UPLOAD 7
#define QUIT 8
struct command{
char cmd[128];
char context[1024];
int flag;
};
服务端:
#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include<arpa/inet.h>
#include <netinet/in.h>
#include<string.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include "parament.h"
int getCmdType(char *cmd)
{
if(strcmp("ls",cmd) == 0){
return LS;
}
if(strcmp("quit",cmd) == 0){
return QUIT;
}
if(strcmp("pwd",cmd) == 0){
return PWD;
}
if(strstr(cmd,"cd") != NULL){
return CD;
}
if(strstr(cmd,"download") != NULL){
return DOWNLOAD;
}
if(strstr(cmd,"upload") != NULL){
return UPLOAD;
}
return 0;
}
char * cmdDetail(char *cmd)
{
char *temp;
temp = strtok(cmd," ");
temp = strtok(NULL," ");
return temp;
}
void comHandler(struct command Cmd,int fd)
{
int ret = getCmdType(Cmd.cmd);
char filename[128];
int filefd;
switch(ret){
case LS:
case PWD:
Cmd.flag = 0;
FILE *f = popen(Cmd.cmd,"r");
fread(Cmd.context,1,sizeof(Cmd.context),f);
write(fd,&Cmd,sizeof(Cmd));
printf("you get my path or file\n");
break;
case CD:
Cmd.flag =0;
strcpy(filename,cmdDetail(Cmd.cmd));
chdir(filename);
printf("into %s\n",filename);
break;
case DOWNLOAD:
strcpy(filename,cmdDetail(Cmd.cmd));
if(access(filename,F_OK) == -1){
Cmd.flag = -1;
strcpy(Cmd.cmd,"server No such file");
write(fd,&Cmd,sizeof(Cmd));
}else{
Cmd.flag = 1;
filefd = open(filename,O_RDWR);
read(filefd,Cmd.context,sizeof(Cmd.context));
close(filefd);
write(fd,&Cmd,sizeof(Cmd));
}
printf("put file to %d client success\n",fd);
break;
case UPLOAD:
Cmd.flag = 0;
strcpy(filename,cmdDetail(Cmd.cmd));
filefd = open(filename,O_CREAT|O_RDWR,0666);
write(filefd,Cmd.context,sizeof(Cmd.context));
close(filefd);
printf("get file from %d client success\n",fd);
break;
case QUIT:
Cmd.flag = 0;
printf("client fd quit\n");
exit(-1);
break;
case 0:
printf("command is wrong\n");
break;
}
}
int main()
{
int s_fd;
int bind_ret;
int listen_ret;
int nread;
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
memset(&s_addr,0,sizeof(struct sockaddr_in));
memset(&c_addr,0,sizeof(struct sockaddr_in));
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(8899);
inet_aton("192.168.191.3",&s_addr.sin_addr);
s_fd = socket(AF_INET,SOCK_STREAM,0);
if(s_fd ==-1){
perror("socket");
exit(-1);
}
bind_ret = bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
if(bind_ret == -1){
perror("bind");
exit(-1);
}
listen_ret = listen_ret = listen(s_fd,10);
if(listen_ret == -1){
perror("listen");
exit(-1);
}
int c_addr_len = sizeof(struct sockaddr_in);
int c_fd;
struct command readBuf;
while(1){
c_fd= accept(s_fd,(struct sockaddr *)&c_addr,&c_addr_len);
if(c_fd == -1){
perror("accept error:");
}
printf("get connect:%s\n",inet_ntoa(c_addr.sin_addr));
if(fork() == 0){
while(1){
memset(readBuf.cmd,0,sizeof(readBuf.cmd));
nread = read(c_fd,&readBuf,sizeof(readBuf));
if(nread == 0){
printf("client out\n");
break;
}else if(nread >0){
printf("from client:%s message:%s",inet_ntoa(c_addr.sin_addr),readBuf.cmd);
comHandler(readBuf,c_fd);
}
}
}
}
close(c_fd);
close(s_fd);
return 0;
}
客户端:
#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include<arpa/inet.h>
#include <netinet/in.h>
#include<string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "parament.h"
int FLAG;
int getCmdType(char *cmd)
{
if(strcmp("ls",cmd) == 0){
return LS;
}
if(strcmp("quit",cmd) == 0){
return QUIT;
}
if(strcmp("lls",cmd) == 0){
return LLS;
}
if(strstr("lcd",cmd) != NULL){
return LCD;
}
if(strcmp("pwd",cmd) == 0){
return PWD;
}
if(strstr(cmd,"cd") != NULL && strstr(cmd,"lcd") == NULL){
return CD;
}
if(strstr(cmd,"download") != NULL){
return DOWNLOAD;
}
if(strstr(cmd,"upload") != NULL){
return UPLOAD;
}
return 0;
}
char * cmdDetail(char *cmd)
{
char *temp;
temp = strtok(cmd," ");
temp = strtok(NULL," ");
return temp;
}
void cmdHandler(struct command Cmd,int fd)
{
int CMD = getCmdType(Cmd.cmd);
char ret[128] = {'\0'};
int filefd;
switch(CMD){
case LS:
case PWD:
case CD:
FLAG = 1;
write(fd,&Cmd,sizeof(Cmd));
break;
case DOWNLOAD:
FLAG=1;
write(fd,&Cmd,sizeof(Cmd));
break;
case UPLOAD:
FLAG=0;
strcpy(ret,cmdDetail(Cmd.cmd));
if(access(ret,F_OK) == -1){
printf("client No such file\n");
}
filefd = open(ret,O_RDWR);
memset(Cmd.context,0,sizeof(Cmd.context));
read(filefd,Cmd.context,sizeof(Cmd.context));
write(fd,&Cmd,sizeof(Cmd));
break;
case LLS:
FLAG=0;
system("ls");
break;
case LCD:
FLAG=0;
strcpy(ret,cmdDetail(Cmd.cmd));
chdir(ret);
break;
case QUIT:
FLAG=0;
strcpy(Cmd.cmd,"quit");
write(fd,&Cmd,sizeof(Cmd));
close(fd);
exit(-1);
break;
}
}
void cmdFromServerhandler(struct command recv,int fd)
{
int nread = read(fd,&recv,sizeof(recv));
int filefd;
if(recv.flag == 1){
char *filename = cmdDetail(recv.cmd);
filefd = open(filename,O_CREAT|O_RDWR,0666);
write(filefd,recv.context,sizeof(recv.context));
}else{
printf("=============================\n");
printf("%s\n",recv.context);
printf("=============================\n");
}
}
int main(int argc,char **argv)
{
int c_fd;
int connect_ret;
struct command sendBuf;
struct command receBuf;
struct sockaddr_in c_addr;
memset(&c_addr,0,sizeof(struct sockaddr_in));
c_addr.sin_family = AF_INET;
c_addr.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1],&c_addr.sin_addr);
c_fd = socket(AF_INET,SOCK_STREAM,0);
if(c_fd ==-1){
perror("socket");
exit(-1);
}
connect_ret = connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr_in));
if(connect_ret == -1){
perror("connect");
exit(-1);
}else{
printf("connect success");
}
while(1){
printf("please input command:");
memset(sendBuf.cmd,0,sizeof(sendBuf.cmd));
gets(sendBuf.cmd);
cmdHandler(sendBuf,c_fd);
if(FLAG == 0){
continue;
}
cmdFromServerhandler(receBuf,c_fd);
}
return 0;
}
代码中的注意事项: 在输入命令的时候由于需要加上空格所以使用gets()进行输入,scanf()会直接将空格之后的内容忽略掉; strtok在使用的时候注意不能直接对常量字符串进行操作,需要把常量字符串转换为字符数组的形式; 项目效果:
|