3.1 main 函数的框架
3.2 首先进行命令行合法性检测
在服务器端应该设置服务器的端口号等信息,通过命令行参数的形式传递给服务器程序:
if (argc != 2)
{
printf("usage: ./ftserve port\n");
exit(0);
}
3.2 获取服务器端口号并创建监听套接字
按理说应该在端口 21 上开启 FTP 服务,这里提供一个更灵活的方式,让操作人员可以自由选择端口。
获取端口号,并转换为整数:
port = atoi(argv[1]);
创建监听套接字:
创建方式可以参看课程 C 语言实现聊天室软件,这里不再赘述。本实验中调用 socket_create 自定义模块创建监听套接字:
if ((sock_listen = socket_create(port)) < 0 )
{
perror("Error creating socket");
exit(1);
}
3.3 创建死循环监听客户机的请求
这部分的框架就是利用创建好的接听套接字 sock_listen 循环监听客户端的连接请求,一旦监听到客户端的连接请求,则创建子进程处理这个已连接的套接字。
监听套接字接受连接请求,得到控制套接字,用于传递控制信息:
sock_control = socket_accept(sock_listen)
创建子进程处理用户请求:
if ((pid = fork()) < 0)
perror("Error forking child process");
子进程调用 ftserve_process 函数与客户端交互
else if (pid == 0)
{
close(sock_listen);
ftserve_process(sock_control);
close(sock_control);
exit(0);
}
四、ftserve_process 模块
ftserve_process 模块提供对某个用户的服务请求。ftserve_process 模块的生命周期是客户端从连接上服务器的开始到结束。完成的功能主要有:
用户认证
处理用户的请求
4.1 模块的框架
4.2 用户认证
首先发送欢迎应答码:
send_response(sock_control, 220);
调用 ftserve_login 函数认证:
if (ftserve_login(sock_control) == 1)
send_response(sock_control, 230);
else
{
send_response(sock_control, 430);
exit(0);
}
4.3 处理用户的请求
首先这是一个利用死循环来不停的接收客户端的指令,来提供服务的:
while (1) {}
下面我们来看看循环体中的内容:
第一步:接收命令,并解析,获得命令和参数:
int rc = ftserve_recv_cmd(sock_control, cmd, arg);
第二步:创建和客户端的数据连接:
sock_data = ftserve_start_data_conn(sock_control)
第三步:执行指令:
if (strcmp(cmd, "LIST")==0)
ftserve_list(sock_data, sock_control);
else if (strcmp(cmd, "RETR")==0)
ftserve_retr(sock_control, sock_data, arg);
五、用户登录
函数 ftserve_login 的逻辑非常简单,先获取用户名和密码,然后调用ftserve_check_user(user, pass) 通过查看 ".auth" 文件 中的用户信息,验证该用户的合法性。
5.1 模块框架
5.2 获取用户名
首先应该接受客户端包含用户名的注册信息,并保存到 buf 中:
if ( (recv_data(sock_control, buf, sizeof(buf)) ) == -1)
{
perror("recv error\n");
exit(1);
}
获得用户名。因为 buf 中的前四个字符为命令字符 USER,所以真正的用户名应该是从 buf[5] 开始的,代码如下:
int i = 5;
int n = 0;
while (buf[i] != 0)
user[n++] = buf[i++];
send_response(sock_control, 331);
5.3 获得用户密码
首先应该接受客户端包含用户密码的信息,并保存到 buf 中:
if ( (recv_data(sock_control, buf, sizeof(buf)) ) == -1)
{
perror("recv error\n");
exit(1);
}
获得用户密码。因为 buf 中的前四个字符为命令字符 PASS,所以真正的用户名应该是从 buf[5] 开始的,代码如下:
i = 5;
n = 0;
while (buf[i] != 0)
pass[n++] = buf[i++];
5.4 用户名和密码验证
调用 ftserve_check_user(user, pass) 函数验证用户的合法性,输入为刚才获得的用户名(user)和密码(pass),代码如下:
return (ftserve_check_user(user, pass));
ftserve_check_user(user, pass) 函数最主要的步骤就是和 ".auth" 文件的信息做比对。
具体代码如下:
if ((strcmp(user,username)==0) && (strcmp(pass,password)==0))
{
auth = 1;
break;
}
来源: 实验楼
链接: https://www.shiyanlou.com/courses/1000
本课程内容,由作者授权实验楼发布,未经允许,禁止转载、下载及非法传播