1、我们先搭建一个一个服务器与客户机并使他们进行通信
2、在客户机中对输入的指令进行判断,将指令转化成对应的枚举类型发送给服务机
3、服务机对发送过来的FTP_CMD的值进行判断,并执行相对应的功能
4、ls功能的实现:通过popen实现,获取内容发送客户机并显示
get 对指令进行分割,读取分割后的文件名所对应的文件,之后将读取后的数据发送给服务机
put 对指令进行分割,将文件读取到data中,发送给客户机,并在服务器中创建文件,将内容写入
quit 直接退出
cd 采用chdir来实现
用户名和密码的实现:从文件读取密码以及账号与用户输入的进行对比,一致通过反之停止
服务器代码
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h> /* See NOTES */
#include <errno.h>
#include "msg.h"
#include "log.h"
#include "utils.h"
int g_running;
/**
*
* @param in_cmd
* @param out_cmd
*/
void handle_cmd(struct Msg *in_cmd, struct Msg *out_cmd)
{
FILE *fp = NULL;
int ret;
out_cmd->cmd = in_cmd->cmd;
switch(in_cmd->cmd) {
case FTP_CMD_LS:
fp = popen(in_cmd->args, "r");
if (NULL != fp) {
ret = fread(out_cmd->data, 1, sizeof(out_cmd->data), fp);
//ret = fread(out_cmd->data, sizeof(out_cmd->data), 1, fp);
log_write("fread ret %d, eof %d, data %s\n",
ret, feof(fp), out_cmd->data);
pclose(fp);
}
break;
default:
break;
}
}
/**
* @brief 澶勭悊瀹㈡埛绔殑鍛戒护in_cmd锛屾妸缁撴灉鍐欏叆out_cmd
*
* @param in_cmd
* @param out_cmd
*/
void handle_cmd2(struct Msg *in_cmd, struct Msg *out_cmd)
{
static struct LinkList *hist = NULL;
log_write("cmd %d, args %s\n", in_cmd->cmd, in_cmd->args);
out_cmd->cmd = in_cmd->cmd;
linklist_insert(&hist, in_cmd->args);
if (FTP_CMD_LS == in_cmd->cmd) {
FILE *fp = popen(in_cmd->args, "r");
if (fp != NULL) {
int ret = fread(out_cmd->data, 1, sizeof(out_cmd->data), fp);
log_write("fread ret %d, %s", ret, out_cmd->data);
pclose(fp);
}
} else if (FTP_CMD_HIST == in_cmd->cmd) {
linklist_get_cmd(hist, out_cmd->data);
} else if (FTP_CMD_CD == in_cmd->cmd) {
char dirname[32];
if (split_string2(in_cmd->args, dirname) < 0) {
return;
}
int ret = chdir(dirname);
log_write("chdir ret %d", ret);
} else if (FTP_CMD_QUIT == in_cmd->cmd) {
log_write("quit\n");
g_running = 0;
} else if (FTP_CMD_GET == in_cmd->cmd) {
char filename[32];
if (split_string2(in_cmd->args, filename) < 0) {
out_cmd->cmd = FTP_CMD_ERROR;
log_write("filename not find\n");
return;
}
long length = get_length(filename);
if (length < 0 || length > sizeof(out_cmd->data)) {
out_cmd->cmd = FTP_CMD_ERROR;
log_write("get_length failed, filename %s\n", filename);
return;
}
get_md5(filename, out_cmd->md5);
FILE *fp = fopen(filename, "r");
if (fp != NULL) {
int ret = fread(out_cmd->data, 1, length, fp);
out_cmd->data_length = ret;
log_write("fread ret %d, eof %d\n", ret, feof(fp));
fclose(fp);
} else {
out_cmd->cmd = FTP_CMD_ERROR;
log_write("filename not find %s\n", filename);
}
} else if (FTP_CMD_PUT == in_cmd->cmd) {
// 鑾峰彇鏂囦欢鍚?浠?寮€澶?
char filename[32];
filename[0] = '+';
split_string2(in_cmd->args, &filename[1]);
FILE *fp = fopen(filename, "w");
if (fp != NULL) {
int ret = fwrite(in_cmd->data, 1, in_cmd->data_length, fp);
log_write("fwrite ret %d, filename %s, data_length %d\n",
ret, filename, in_cmd->data_length);
fclose(fp);
}
// 瀵规瘮瀹㈡埛绔殑md5
char md5[64];
get_md5(filename, md5);
if (memcmp(md5, in_cmd->md5, 32) != 0) {
remove(filename);
log_write("client %s, server %s\n", in_cmd->md5, md5);
}
}
}
int main(int argc, char **argv)
{
struct sockaddr_in serveraddr;
int listenfd;
int sock;
int ret;
struct Msg *msg_recv = NULL;
struct Msg *msg_send = NULL;
msg_recv = (struct Msg *)malloc(sizeof(struct Msg));
msg_send = (struct Msg *)malloc(sizeof(struct Msg));
log_create("server.txt");
// socket
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if (listenfd < 0) {
log_write("socket failed, ret %d\n", listenfd);
return -1;
}
// bind绔彛锛孲ERVER_PORT
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = SERVER_PORT;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
int on = 1;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
ret = bind(listenfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
if (ret < 0) {
log_write("bind failed, ret %d, errno %d %s\n", ret, errno, strerror(errno));
return -1;
}
ret = listen(listenfd, 0);
if (ret < 0) {
log_write("listen failed ,ret %d\n", ret);
return -1;
}
sock = accept(listenfd, NULL, 0);
if (ret < 0) {
log_write("accept failed ,ret %d\n", ret);
return -1;
}
log_write("client connect.\n");
struct Auth auth;
ret = recv(sock, &auth, sizeof(struct Auth), 0);
log_write("%s %s\n", auth.username, auth.password);
struct Auth server;
FILE *fp = fopen("passwd", "r");
if (fp != NULL) {
fscanf(fp, "%s %s", server.username, server.password);
log_write("server %s %s\n", server.username, server.password);
fclose(fp);
}
if (0 != memcmp(auth.username, server.username, strlen(server.username)) ||
0 != memcmp(auth.password, server.password, strlen(server.password))) {
// 涓嶄竴鏍?
auth.cmd = FTP_CMD_ERROR;
log_write("auth failed\n");
}
ret = send(sock, &auth, sizeof(struct Auth), 0);
log_write("send %d\n", ret);
if (FTP_CMD_ERROR == auth.cmd) {
return -1;
}
g_running = 1;
while (g_running) {
ret = recv(sock, msg_recv, sizeof(struct Msg), 0);
log_write("recv %d\n", ret);
memset(msg_send, 0, sizeof(struct Msg));
handle_cmd2(msg_recv, msg_send);
ret = send(sock, msg_send, sizeof(struct Msg), 0);
log_write("send %d\n", ret);
}
log_destroy();
return 0;
}
客户机
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h> /* See NOTES */
#include "log.h"
#include "msg.h"
#include "utils.h"
enum FTP_CMD get_cmd(char *buf, struct Msg *msg)
{
char *ptr_args;
if (0 == memcmp(buf, "ls", 2)) {
return FTP_CMD_LS;
}
return FTP_CMD_ERROR;
}
int handle_user_input(struct Msg *msg_send)
{
char buf[32];
enum FTP_CMD cmd;
printf("input cmd:\n");
fgets(buf, 32, stdin);
log_write("%s\n", buf);
cmd = get_cmd(buf, msg_send);
log_write("cmd %d\n", cmd);
if (cmd == FTP_CMD_ERROR) {
return -1;
}
msg_send->cmd = cmd;
strcpy(msg_send->args, buf);
return 0;
}
int handle_user_input2(struct Msg *msg_send)
{
char buf[32];
enum FTP_CMD cmd;
fgets(buf, 32, stdin);
log_write("%s", buf);
if (0 == memcmp(buf, "ls", 2)) {
cmd = FTP_CMD_LS;
} else if (0 == memcmp(buf, "hist", 4)) {
cmd = FTP_CMD_HIST;
} else if (0 == memcmp(buf, "cd", 2)) {
cmd = FTP_CMD_CD;
} else if (0 == memcmp(buf, "get", 3)) {
cmd = FTP_CMD_GET;
} else if (0 == memcmp(buf, "quit", 4)) {
cmd = FTP_CMD_QUIT;
} else if (0 == memcmp(buf, "put", 3)) {
cmd = FTP_CMD_PUT;
char filename[32];
if (split_string2(buf, filename) < 0) {
log_write("filename not find");
return -1;
}
long length = get_length(filename);
if (length < 0 || length > sizeof(msg_send->data)) {
log_write("get_length failed, length %d\n", length);
return -1;
}
get_md5(filename, msg_send->md5);
// #define NULL 0
FILE *fp = fopen(filename, "r");
if (NULL != fp) {
// 璁剧疆data_length
msg_send->data_length = fread(msg_send->data, 1, length, fp);
log_write("fread %d", msg_send->data_length);
fclose(fp);
} else {
log_write("filename not find, %s", filename);
return -1;
}
} else {
cmd = FTP_CMD_ERROR;
}
if (cmd == FTP_CMD_ERROR) {
return -1;
}
msg_send->cmd = cmd;
strcpy(msg_send->args, buf);
return 0;
}
int main(int argc, char **argv)
{
int ret;
int sock;
struct sockaddr_in serveraddr;
struct Msg *msg_send = NULL;
struct Msg *msg_recv = NULL;
msg_send = (struct Msg *)malloc(sizeof(struct Msg));
msg_recv = (struct Msg *)malloc(sizeof(struct Msg));
log_create("client.txt");
sock = socket(AF_INET, SOCK_STREAM, 0);
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = SERVER_PORT;
serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
// 3. 杩炴帴connect
ret = connect(sock, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
if (ret < 0) {
log_write("connect failed, ret %d\n", ret);
return -1;
}
log_write("connect server sucess\n");
struct Auth auth;
printf("username:");
scanf("%s", auth.username);
printf("password:");
scanf("%s", auth.password);
auth.cmd = FTP_CMD_AUTH;
ret = send(sock, &auth, sizeof(struct Auth), 0);
log_write("send ret %d", ret);
ret = recv(sock, &auth, sizeof(struct Auth), 0);
if (FTP_CMD_ERROR == auth.cmd) {
printf("username or password error\n");
return -1;
}
printf("well done\n");
while(1) {
if (handle_user_input2(msg_send) < 0) {
continue;
}
ret = send(sock, msg_send, sizeof(struct Msg), 0);
log_write("send ret %d\n", ret);
ret = recv(sock, msg_recv, sizeof(struct Msg), 0);
log_write("recv ret %d\n", ret);
log_write("cmd %d\n", msg_recv->cmd);
log_write("data %s\n", msg_recv->data);
if (FTP_CMD_HIST == msg_recv->cmd || FTP_CMD_LS == msg_recv->cmd) {
printf("%s", msg_recv->data);
} else if (FTP_CMD_GET == msg_recv->cmd) {
// get file.txt
// file.txt
// _file.txt
char filename[32];
filename[0] = '_';
split_string2(msg_send->args, &filename[1]);
FILE *fp = fopen(filename, "w");
if (fp != NULL) {
ret = fwrite(msg_recv->data, 1, msg_recv->data_length, fp);
log_write("fwrite ret %d", ret);
fclose(fp);
}
char md5[64];
get_md5(filename, md5);
if (memcmp(md5, msg_recv->md5, 32) != 0) {
remove(filename);
log_write("client %s, server %s\n", msg_recv->md5, md5);
}
} else if (FTP_CMD_QUIT == msg_recv->cmd) {
printf("byebye\n");
break;
}
}
log_destroy();
return 0;
}