当我尝试使用 ftp 访问 ls 命令时,我总是在 PORT 部分中点击 425,有人能告诉我这是为什么吗?我的用户部分工作正常,如果我能让端口工作,我就可以专注于 STOR 和 RETR。
/*FTP server*/
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/*for getting file size using stat()*/
#include<sys/stat.h>
/*for sendfile()*/
#include<sys/sendfile.h>
/*for O_RDONLY*/
#include<fcntl.h>
int active=0;
int sock1, sock2;
char buf[100], command[5], filename[20];
struct sockaddr_in remoteaddr, remoteaddr_data;
int main(int argc,char *argv[])
{
struct sockaddr_in server, client;
struct stat obj;
struct sockaddr_in local_data_addr_act;
int s, s_data, s_data_act;
s = socket(AF_INET, SOCK_STREAM, 0);
s_data = socket(AF_INET, SOCK_STREAM, 0);
s_data_act = socket(AF_INET, SOCK_STREAM, 0);
int k, i, size, len, c;
int filehandle;
sock1 = socket(AF_INET, SOCK_STREAM, 0);
if(sock1 == -1)
{
printf("Socket creation failed");
exit(1);
}
server.sin_port = htons(atoi(argv[1]));
server.sin_addr.s_addr = 0;
k = bind(sock1,(struct sockaddr*)&server,sizeof(server));
if(k == -1)
{
printf("Binding error");
exit(1);
}
k = listen(sock1,1);
if(k == -1)
{
printf("Listen failed");
exit(1);
}
len = sizeof(client);
sock2 = accept(sock1,(struct sockaddr*)&client, &len);
write(sock2,"220\r\n", 6);
i = 1;
while(1)
{
recv(sock2, buf, 100, 0);
printf("%s\n", buf);
sscanf(buf, "%s", command);
printf("%s\n", command);
if(!strcmp(command, "LIST"))
{
system("ls >tmp.txt");
FILE *fin=fopen("tmp.txt","r");
sprintf(buf, "125\r\n");
send(sock2, buf, strlen(buf), 0);
char temp_buf[10];
while (!feof(fin))
{
fgets(temp_buf, 98, fin);
sprintf(buf, "%s", temp_buf);
if (!active)send(sock1, buf, strlen(buf), 0);
else send(s_data_act, buf, strlen(buf), 0);
}
fclose(fin);
sprintf(buf, "250\r\n");
send(sock2, buf, strlen(buf), 0);
if(!active) close(sock1);
else close(s_data_act);
sprintf(buf, "226\r\n");
send(sock2, buf, strlen(buf), 0);
}
else if(!strcmp(command,"USER"))
{
sprintf(buf, "230\r\n");
send(sock2, buf, strlen(buf), 0);
}
else if(!strcmp(command,"SYST"))
{
write(sock2, "502\r\n", 6);
}
else if(!strcmp(command,"PORT"))
{
unsigned char act_port[2];
int act_ip[4], port_dec;
char ip_decimal[40];
active=1;
sscanf(command, "PORT %d,%d,%d,%d,%d,%d",&act_ip[0],&act_ip[1],&act_ip[2],&act_ip[3], &act_port[0], &act_port[1]);
local_data_addr_act.sin_family=AF_INET;
sprintf(ip_decimal, "%d.%d.%d.%d", act_ip[0], act_ip[1], act_ip[2], act_ip[3]);
local_data_addr_act.sin_addr.s_addr=inet_addr(ip_decimal);
port_dec=act_port[0];
port_dec=port_dec<<8;
port_dec=port_dec+act_port[1];
local_data_addr_act.sin_port=htons(port_dec);
if (connect(s_data_act,(struct sockaddr*)&local_data_addr_act, (int)sizeof(struct sockaddr))!=0)
{
printf("%s%d\n",inet_ntoa(local_data_addr_act.sin_addr),ntohs(local_data_addr_act.sin_port));
sprintf(buf, "425\r\n");
send(sock2, buf, strlen(buf), 0);
close(s_data_act);
}
else
{
sprintf(buf, "200\r\n");
send(sock2, buf, strlen(buf), 0);
}
}
else if(!strcmp(command,"RETR"))
{
sscanf(buf, "%s%s", filename, filename);
stat(filename, &obj);
filehandle = open(filename, O_RDONLY);
size = obj.st_size;
if(filehandle == -1)
size = 0;
send(sock2, &size, sizeof(int), 0);
if(size)
sendfile(sock2, filehandle, NULL, size);
}
else if(!strcmp(command, "STOR"))
{
int c = 0, len;
char *f;
sscanf(buf+strlen(command), "%s", filename);
recv(sock2, &size, sizeof(int), 0);
i = 1;
while(1)
{
filehandle = open(filename, O_CREAT | O_EXCL | O_WRONLY, 0666);
if(filehandle == -1)
{
sprintf(filename + strlen(filename), "%d", i);
}
else
break;
}
f = malloc(size);
recv(sock2, f, size, 0);
c = write(filehandle, f, size);
close(filehandle);
send(sock2, &c, sizeof(int), 0);
}
else if(!strcmp(command, "pwd"))
{
system("pwd>temp.txt");
i = 0;
FILE*f = fopen("temp.txt","r");
while(!feof(f))
buf[i++] = fgetc(f);
buf[i-1] = '\0';
fclose(f);
send(sock2, buf, 100, 0);
}
else if(!strcmp(command, "cd"))
{
if(chdir(buf+3) == 0)
c = 1;
else
c = 0;
send(sock2, &c, sizeof(int), 0);
}
else if(!strcmp(command, "bye") || !strcmp(command, "QUIT"))
{
printf("FTP server quitting..\n");
i = 1;
send(sock2, &i, sizeof(int), 0);
exit(0);
}
}
return 0;
}
最佳答案
这段代码充满了错误和错误。无论您尝试使用此代码实现什么,它都与符合要求的 FTP 服务器实现相差甚远。
您创建了太多套接字,甚至没有使用所有套接字。而且您在错误的时间、错误的条件下创建了其中一些。
大多数套接字/文件函数调用完全缺乏错误处理。
没有正确处理套接字读/写,特别是没有考虑到 TCP 是一种流传输,不提供任何写入和读取之间一对一关系的保证。您必须必须考虑到这一点!
有时向客户端写入不正确的数据 - 发送不期望的空终止符,发送数据缓冲区,就像它们实际上不是空终止一样,在不期望时将文件大小作为二进制整数发送,等等。
假设接收到的数据以 null 终止,但事实并非如此。
将被动模式数据发送到错误的套接字(甚至没有执行 PASV
命令)。
没有正确执行PORT
、STOR
和RETR
命令(对套接字管理不当)。
未正确执行 PWD
、CD
和 BYE
/QUIT
命令(发送完全无效的回复) .
而且,虽然从技术上来说不是错误,但您确实不应该使用 system()
。有更好的本地方法来获取所需的数据。对于LIST
,您可以使用opendir()
代替,然后根据需要写入目录的条目。对于PWD
,您可以使用getcwd()
。
您需要废弃此代码并重新开始。它有太多问题需要尝试修复。网上有很多关于如何正确实现套接字 I/O 的示例,尤其是如何使用套接字进行基于行的 I/O(因为 FTP 是基于行的协议(protocol))。请阅读RFC 959了解处理 FTP 命令/响应和数据传输管理的正确规则。
关于c - 初学者 ftp 服务器困境,部分 deux,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29908687/