-
Notifications
You must be signed in to change notification settings - Fork 1
/
Service.cpp
executable file
·169 lines (149 loc) · 4.3 KB
/
Service.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#include "Service.h"
Service::Service(int command_sockfd){
this->command_sockfd = command_sockfd;
current_path = ".";
}
Service::~Service(){
}
//运行服务器
void Service::start(){
bool continue_flag = true;
//处理传来的命令
while(continue_flag){
if(recvCommand() < 0){
HandleError::handleError("data", HandleError::receive_error);
close(command_sockfd);
break;
}
cout << "recv command: " << command_buffer << endl;
continue_flag = handleCommand();
}
}
//建立数据连接
bool Service::createDataSocket(){
//建立数据连接
int listen_data_sockfd = createSocket();
if (listen_data_sockfd < 0){
HandleError::handleError("data", HandleError::initial_socket_error);
return false;
}
setAddr(data_sin);//设置本机地址与任意可用端口号
if(bind(listen_data_sockfd, (struct sockaddr*)&data_sin, sizeof(data_sin)) != 0){
HandleError::handleError("data", HandleError::bind_error);
return false;
}
//获得系统给的可用端口号
socklen_t data_sin_len = sizeof(data_sin);
if(getsockname(listen_data_sockfd, (sockaddr*)&data_sin, &data_sin_len)){
HandleError::handleError("data", HandleError::getsockname_error);
return false;
}
if(listen(listen_data_sockfd, 1) != 0){
HandleError::handleError("data", HandleError::listen_error);
return false;
}
//发送端口号
*((short*)command_buffer) = data_sin.sin_port;
sendCommand();
//cout << "server port: " << ntohs(data_sin.sin_port) << ", ";
//数据连接建立
data_sockfd = accept(listen_data_sockfd, (struct sockaddr*)&data_sin, &data_sin_len);
if(data_sockfd < 0){
HandleError::handleError("data", HandleError::accept_error);
return false;
}
//cout << "build data connection successfully!" << endl;
return true;
}
//发送命令
inline int Service::sendCommand(){
return write(command_sockfd, command_buffer, COMMAND_BUF_SIZE);
}
//接收命令
inline int Service::recvCommand(){
return read(command_sockfd, command_buffer, COMMAND_BUF_SIZE);
}
//发送数据
inline int Service::sendData(){
return write(data_sockfd, data_buffer, DATA_BUF_SIZE);
}
//接收数据
inline int Service::recvData(){
return read(data_sockfd, data_buffer, DATA_BUF_SIZE);
}
//解析命令并处理命令,若命令为quit则返回false,否则返回true
bool Service::handleCommand(){
split(command_buffer, ' ', command);
if (command.empty())
return true;
if(command[0] == SERVER_RETR_COMMAND){
RETR_command(command[1]);
}
else if(command[0] == SERVER_STOR_COMMAND){
STOR_command(command[1]);
}
else if(command[0] == SERVER_PWD_COMMAND){
PWD_command();
}
else if(command[0] == SERVER_LIST_COMMAND){
LIST_command();
}
else if(command[0] == SERVER_CWD_COMMAND){
CWD_command(command[1]);
}
else if(command[0] == SERVER_QUIT_COMMAND){
QUIT_command();
return false;
}
else{
cout << "unknown command" << endl;
}
return true;
}
//处理RETR命令
void Service::RETR_command(string file_name){
if(file_exist(current_path, file_name)){
command_buffer[0] = FILE_EXIST;
sendCommand();
if(!createDataSocket()) return;
send_file(data_sockfd, current_path + "/" + file_name, data_buffer, DATA_BUF_SIZE);
close(data_sockfd);
}
else{
command_buffer[0] = FILE_NOT_EXIST;
sendCommand();
}
}
//处理STOR命令
void Service::STOR_command(string file_name){
if(!createDataSocket()) return;
recv_file(data_sockfd, current_path + "/" + file_name, data_buffer, DATA_BUF_SIZE);
close(data_sockfd);
}
//处理PWD命令
void Service::PWD_command(){
strcpy(command_buffer, current_path.c_str());
sendCommand();
}
//处理LIST命令
void Service::LIST_command(){
list_file(current_path, command_buffer, COMMAND_BUF_SIZE);
sendCommand();
}
//处理CWD命令
void Service::CWD_command(string path){
bool path_exist;
current_path = cwd(current_path, path, path_exist);
if(!path_exist){
strcpy(command_buffer, "file doesn't exist!\n");
}
else{
strcpy(command_buffer, "");
}
sendCommand();
}
//处理QUIT命令
void Service::QUIT_command(){
close(command_sockfd);
cout << "client disconnect" << endl;
}