Пассивная розетка не принимает 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)
    ...
Другие вопросы по тегам