你记得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)
...