Я делаю реализацию FTP, теперь я реализую команду RETR, я беру код ошибки 88, когда пытаюсь выполнить команду «получить имя файла».
Я думаю, что ошибка может быть преобразованием unsigned в uint32_t и uint16_t в команде порта.
#include <cstring>
#include <cstdarg>
#include <cstdio>
#include <cerrno>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <locale.h>
#include <langinfo.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <iostream>
#include <dirent.h>
#include "common.h"
#include "ClientConnection.h"ClientConnection::ClientConnection(int s) {
int sock = (int)(s);
char buffer[MAX_BUFF];
control_socket = s;
// Consultar la documentación para conocer el funcionamiento de fdopen.
fd = fdopen(s, "a+");
if (fd == NULL){
std::cout << "Connection closed" << std::endl;
fclose(fd);
close(control_socket);
ok = false;
return ;
}
ok = true;
data_socket = -1;};ClientConnection::~ClientConnection() {
fclose(fd);
close(control_socket);
}int connect_TCP(uint32_t address, uint16_t port) {
struct sockaddr_in sin;
struct hostent
*hent;
int s;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = address;
//if(hent = gethostbyname(address))
//memcpy(&sin.sin_addr,hent->h_addr,hent->h_length);
//else if ((sin.sin_addr.s_addr = inet_addr((char*)address)) == INADDR_NONE)
//errexit("No puedo resolver el nombre \"%s\"\n", address);s = socket(AF_INET, SOCK_STREAM, 0);
if(s < 0){
printf("No se puede crear el socket\n");
return 0;
}
if(connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0){
printf("No se puede conectar con %u\n", address);
return 0;
}
return s;
}void ClientConnection::stop() {
close(data_socket);
close(control_socket);
parar = true;
}#define COMMAND(cmd) strcmp(command, cmd)==0void ClientConnection::WaitForRequests() {
if (!ok) {
return;
}
fprintf(fd, "220 Service ready\n");
while(!parar) {
fscanf(fd, "%s", command);
if (COMMAND("USER")) {
fscanf(fd, "%s", arg);
fprintf(fd, "331 User name ok, need password\n");
}
else if (COMMAND("PWD")) {
}
else if (COMMAND("PASS")) {
char pass[30];
fscanf(fd,"%s",pass);
fprintf(fd,"230 User logged in\n");
}
else if (COMMAND("PORT")) {
unsigned ip[4];
unsigned port[2];
fscanf(fd,"%u,%u,%u,%u,%u,%u",&ip[0],&ip[1],&ip[2],&ip[3],&port[0],&port[1]);uint32_t aux1;
uint16_t aux2;
aux1 = ip[3] << 24 | ip[2] << 16 | ip[1] << 8 | ip[0];
aux2 = port[1]*256 + port[0];
data_socket = connect_TCP(aux1,aux2);
fprintf(fd,"200 OK\n");
}
else if (COMMAND("PASV")) {
}
else if (COMMAND("CWD")) {
}
else if (COMMAND("STOR") ) { //put
FILE* fp = fopen("filename","w+");
int size_buffer = 512;
char buffer[size_buffer];
int recived_datas;
while(recived_datas == size_buffer){
datos_recibidos = recv(data_socket,buffer,size_buffer,0);
fwrite(buffer,1,recived_datas,fp);
}
close(data_socket);
fclose(fp);
}
else if (COMMAND("SYST")) {
fprintf(fd,"SYSTEM DETAILS\n");
}
else if (COMMAND("TYPE")) {
fprintf(fd,"type 1");
}
else if (COMMAND("RETR")) {
fscanf(fd,"%s",arg);
std::cout << "Argument: " << arg << std::endl;
FILE* fp = fopen(arg,"r+");
int sent_datas;
int size_buffer = 512;
char buffer[size_buffer];
std::cout << "Buffer size = " << size_buffer << std::endl;
do{
sent_datas = fread(buffer,size_buffer,1,fp);
printf("Code %d | %s\n",errno,strerror(errno));
send(data_socket,buffer,sent_datas,0);
printf("Code %d | %s\n",errno,strerror(errno));
}while(sent_datas == size_buffer);
close(data_socket);
fclose(fp);
fprintf(fd,"Transferencia completada");
}
else if (COMMAND("QUIT")) {
}
else if (COMMAND("LIST")) {
}
else {
fprintf(fd, "502 Command not implemented.\n"); fflush(fd);
printf("Comando : %s %s\n", command, arg);
printf("Error interno del servidor\n");
}
}
fclose(fd);return;
};
Код ошибки 88 ENOTSOCK
Это означает, что вы пытались выполнить операцию с сокетом на «не сокете».
Оскорбительная линия, я считаю, это:
send(data_socket,buffer,sent_datas,0);
Похоже, в вашем разделе RETR вы никогда не устанавливали data_socket
в действительный сокет с вашим connect_TCP
функция, как вы сделали в ПОРТ. Вы уверены, что data_socket
является действительным FD, когда вы вызываете функцию RETR?