Пассивная розетка не принимает ftp
Я делаю FTP-сервер, и когда я пытаюсь подключиться к нему с помощью filezilla, сервер не принимает соединение на пассивном сокете. Он зависает при принятии вызова. Вот часть моего кода:
if ((server->pasv_sock = accept(server->sockt, (struct sockaddr*)&sin_clt,
(socklen_t*)&size_sin) == -1))
Мой сокет привязан к определенному порту, и клиент пытается соединиться с этим. Telnet тоже не подключается.
Если вы можете помочь мне найти, что не так, спасибо:)
1 ответ
Вы не забыли позвонить listen
до accept
?
Помните: socket
-> bind
-> listen
-> accept
,
Изменить: Вот некоторые комментарии к вашему коду.
struct protoent *pe;
struct sockaddr_in sin;
int sock;
struct sockaddr_in sin_clt;
int size_sin;
if ((pe = getprotobyname("TCP")) == NULL)
perro("getprotobyname");
sock = xsocket(AF_INET, SOCK_STREAM, pe->p_proto);
С помощью getprotobyname
не требуется, так как имя жестко запрограммировано и в любом случае есть только один протокол IP-потока. использование 0
вместо pe->p_proto
и не звоните getprotobyname
,
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
Вы не инициализируете sin.sin_port
, Это ошибка.
while (bind(sock, (const struct sockaddr*)&sin,
(socklen_t)sizeof(sin)) == -1 && server->port2 <= 65535)
sin.sin_port = htons(server->port2++);
Этот цикл немного беспорядок. Это может быть в основном правильно, но трудно сказать. Давайте перепишем его так, чтобы он был явно правильным, а не явно неправильным.
if (listen(sock, 1) == -1)
perror("listen");
size_sin = sizeof(sin_clt);
if ((server->pasv_sock = accept(sock, (struct sockaddr*)&sin_clt,
(socklen_t*)&size_sin) == -1))
Это определенно не делает то, что вы хотите.
Обсуждение: я добавлю скобки в последнюю строку, чтобы показать вам, что он на самом деле делает.
if ((server->pasv_sock = accept(...) == -1))
такой же как
if ((server->pasv_sock = (accept(...) == -1)))
Я предполагаю, что вы получили предупреждение компилятора, которое жаловалось на назначение, в котором предлагалось добавить скобки... но добавленные вами скобки были не в том месте. Причина, по которой компилятор предупреждал вас, заключалась в том, что это распространенный источник ошибок, и для компилятора невозможно понять, что вы на самом деле подразумеваете под этим утверждением. Вы имеете в виду что-то более похожее на это:
if ((server->pasv_sock = accept(...)) == -1)
Но я не рекомендую это. Легче читать и более надежно вытащить назначения из предикатов if,
server->pasv_sock = accept(...);
if (server->pasv_sock == -1)
И нет, нет никакой разницы в конечном коде сборки; так что нет разницы в производительности.
Есть еще одна проблема с этой линией, но она несколько педантичная. Вы не должны бросать (socklen_t *) &size_sin
, Вместо этого вы должны изменить объявление size_sin
иметь socklen_t
тип для начала. Единственная причина, по которой это работает, потому что socklen_t
определяется по типу int
, но сделайте вид, что вы этого не знаете, и используйте правильный тип для начала.
Образец кода:
int port, sock, r, csock;
struct sockaddr_in saddr, caddr;
socklen_t caddrlen;
// This is a simpler way to get a TCP socket
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) abort();
// Loop over available ports, and bind to one
// (I'm not sure if this is the best way to do this)
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = INADDR_ANY;
for (port = 10000; port < 65536; ++port) {
saddr.sin_port = htons(port);
r = bind(sock, (struct sockaddr *) &saddr, (socklen_t) sizeof(saddr));
if (!r)
break;
}
if (r) abort();
// Listen and accept a connection
r = listen(sock, 1);
if (r < 0) abort();
caddrlen = (socklen_t) sizeof(caddr);
csock = accept(sock, (struct sockaddr *) &caddr, &caddrlen);
if (csock < 0) abort();
// You don't want to listen for more connections
close(sock);
Рекомендации: пока старайтесь избегать побочных эффектов (accept
, bind
, назначения и т. д.) в условных выражениях. Я не говорю, что это никогда не нормально, но похоже, что именно здесь ваши проблемы, и очень легко просто перенести побочные эффекты в отдельную строку кода, а затем выполнить окончательное сравнение только в условии if или пока состояние.
// Both of these are correct.
// The bottom one is obviously correct.
// Correctness is not always good enough.
// Being obviously correct is important!
if ((p->x = func()) == NULL)
...
p->x = func();
if (p->x == NULL)
...