被动套接字不接受ftp

时间:2012-04-08 00:37:39

标签: c sockets passive-mode

我正在制作一个ftp服务器,当我尝试使用filezilla连接它时,服务器不接受被动套接字上的连接。它挂在接听电话上。 这是我的代码的一部分:

if ((server->pasv_sock = accept(server->sockt, (struct sockaddr*)&sin_clt, (socklen_t*)&size_sin) == -1))

我的套接字绑定到特定端口,客户端尝试连接此端口。 Telnet也没有连接。

如果你能帮我找到错误,谢谢你:)

1 个答案:

答案 0 :(得分: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)

但我不建议这样做。更易于阅读和更加万无一失的是从谓词中提取分配,

server->pasv_sock = accept(...);
if (server->pasv_sock == -1)

不,结果汇编代码没有区别;所以没有性能差异。

这条线还有另一个问题,但它有些迂腐。你不应该施放(socklen_t *) &size_sin。相反,您应该更改size_sin的声明以使socklen_t类型开头。它起作用的唯一原因是因为socklen_tint的类型定义,但假装你不知道并使用正确的类型开始。

示例代码:

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);

Reccomendations:目前,请尽量避免在条件限制中放置副作用(acceptbind,作业等。我并不是说这样做是不可能的,但看起来这就是你的问题所在,并且很容易将副作用转移到单独的代码行,然后执行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)
    ...