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