【发布时间】:2016-01-19 15:37:35
【问题描述】:
我正在尝试在 C/C++ 中创建一个简单的 FTP 客户端,它将执行简单的操作(连接、检索文件)。到目前为止我所做的是连接和登录。我使用套接字连接到端口 21,就像任何常规 FTP 客户端一样。我遇到的问题是连接到输入命令 PASV 时指定的端口。我收到消息,解析它,然后在输入 PASV 时从重播消息中计算端口。
227 Entering Passive Mode (a1, a2, a3, a4, p1, p2)
DataPort = (p1 * 256) + p2
一旦有了端口,我就会尝试创建另一个套接字并以相同的方式连接到它。这就是我的问题所在。到目前为止,我的代码发布在下面。我不知道我是否需要以同样的方式再次获取服务器地址。我没有从服务器得到回复(如果我真的想得到一个,我不知道)请提出任何问题或疑虑,谢谢。
const int FTP_PORT = 21; // Server Port
const int SIZE = 1024; // Size of Buffers
char receiveBuff[SIZE]; // Buffer to send to the server
char sendBuff[SIZE]; // Buffer to receive from server
char pasvBuff[] = "pasv"; // Buffer to see if PASV Command was entered
char quitBuff[] = "QUIT"; // Buffer to see if QUIT Command was entered
char pasvMessage[100]; // String for PASV information
int main(int argc, char *argv[])
{
int length = 0, i=0;
int a1, a2, a3, a4, p1, p2, dataPort; //PASV Information
/* Get Server Name from User */
if (argc != 2)
{
cerr << "Usage: " << argv[0] << " server" << endl;
return 1;
}
/* Obtain Host (Server) Info */
struct hostent *host;
host = gethostbyname(argv[1]);
if (host == (struct hostent *)NULL)
{
perror("Client: gethostbyname");
return 2;
}
/* Add Server Information */
struct sockaddr_in servAdr; // Internet address of server
memset(&servAdr, 0, sizeof(servAdr)); // Clear structure
servAdr.sin_family = AF_INET; // Set address typedef
memcpy(&servAdr.sin_addr, host->h_addr, host->h_length);
servAdr.sin_port = htons(FTP_PORT); // Use FTP port
/* Create Socket to Connect to FTP Server */
int origSock; // Original socket in client
if ((origSock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Client: generate error");
return 3;
}
/* Connect to FTP Server on Port 21 */
if (connect(origSock, (struct sockaddr *)&servAdr, sizeof(servAdr)) < 0)
{
perror("Client: connect error");
return 4;
}
/* Get Conenct Message and Print to Screen */
read(origSock, receiveBuff, sizeof(receiveBuff) - 1);
write(fileno(stdout), receiveBuff, sizeof(receiveBuff) - 1);
do
{
/* Clear Buffers */
memset(receiveBuff, 0, SIZE);
memset(sendBuff, 0, SIZE);
write(fileno(stdout), "Please enter a FTP Command: ", 28); // Write User Interface
read(fileno(stdin), sendBuff, SIZE); // Read Command from User
send(origSock, sendBuff, strlen(sendBuff) , 0); // Send Command to Server
read(origSock, receiveBuff, sizeof(receiveBuff) - 1); // Read Response from Server
write(fileno(stdout), receiveBuff, sizeof(receiveBuff) - 1); // Print Response from Server to screen
/* If PASV Command was Entered */
if (strncmp(sendBuff, pasvBuff, 4) == 0)
{
sscanf(receiveBuff, "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)", &a1,&a2,&a3,&a4,&p1,&p2);
dataPort = (p1 * 256) + p2;
struct sockaddr_in servAdr2; // Internet address of server
memset(&servAdr2, 0, sizeof(servAdr2)); // Clear structure
servAdr2.sin_family = AF_INET; // Set address typedef
memcpy(&servAdr2.sin_addr, host->h_addr, host->h_length);
servAdr.sin_port = htons(dataPort); // Use FTP port
/* Create Socket to Connect to FTP Server */
int dataSock; // Data socket in client
if ((dataSock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Client: generate error");
return 3;
}
/* Connect to FTP Server on Data Port */
if (connect(dataSock, (struct sockaddr *)&servAdr, sizeof(servAdr)) < 0)
{
perror("Client: connect error");
return 4;
}
read(dataSock, receiveBuff, sizeof(receiveBuff) - 1);
write(fileno(stdout), receiveBuff, sizeof(receiveBuff) - 1);
}
} while (strncmp(sendBuff, quitBuff, 4) != 0); // Go until QUIT Command is entered
close(origSock);
return 0;
}
【问题讨论】:
-
“C/C++”不是一个东西。
-
“我没有从服务器得到响应” 太宽泛了。有很多情况会发生这种情况。防火墙、NAT 映射、端口限制。特别是你应该检查任何错误情况,你可能会遇到套接字操作。
-
差不多,我看看我是否真的正确地进行了第二次连接?这就是我遇到麻烦的地方,我想我会从服务器得到某种响应。
-
您需要查看
read()的返回值,以了解您实际从套接字中读取了多少数据。 -
因为还没有什么要读的。您还没有发送任何命令来告诉服务器实际发送任何数据。
PASV只是打开服务器的数据端口。您必须发送STOR和RETR命令才能通过开放数据端口执行传输。