0

ftpサーバーを作成していますが、filezillaで接続しようとすると、サーバーがパッシブソケットでの接続を受け入れていません。受諾呼び出しでハングします。これが私のコードの一部です:

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

私のソケットは特定のポートにバインドされており、クライアントはこのポートに接続しようとします。Telnetも接続していません。

あなたが私が何が悪いのかを見つけるのを手伝ってくれるなら、ありがとう:)

4

1 に答える 1

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ストリームプロトコルは1つしかないため、使用する必要はありません。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がtypedefedであるためです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)
    ...
于 2012-04-08T00:50:07.067 に答える