我正在Linux上用C语言调试一个非常基本的tcp服务器.我在调用accept()的行之前停止了执行.令我惊讶的是,当客户端发送SEN时,tcpdump显示服务器用SYN-ACK进行响应(很容易用客户端的最终ACK进行回复).
ss命令确实表明应用程序已经在监听绑定端口.
我知道我已经调用了listen(),因此应用程序将监听绑定的端口.但根据同样的语义,应该在服务器接受连接之前调用accept().
在listen()手册页面中,它写道(Italian是我的):
listen()将sockph引用的插槽标记为被动插槽,即socket that will be used to accept incoming connection requests using accept(2).
而accept()手册页上写道:
它提取监听插座的前connection request on the queue of pending connections个
由此可以理解,在建立连接之前应该调用accept().
我在这里错过了什么?如果这是标准行为,我可以被指出给主要来源吗?或者只是具体实施?
下面是我正在使用的代码.如果我在调用listen()之前停止执行它,使用netcat会显示发送的SEN会被一个RST回复.但如果我在执行listen()后执行同样的操作,tcpdump将显示服务器回复SYN-ACK.
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
void error(const char* message) {
printf("%s %s\n", message, strerror(errno));
}
int main(int argc, char** argv) {
const int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if ( sockfd == -1 ) {
error("Socket error:");
return 1;
}
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(12345);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if ( bind(sockfd, (struct sockaddr*) &servaddr, sizeof(servaddr)) == - 1 ) {
error("Bind error:");
return 1;
}
if ( listen(sockfd, 5) == -1 ) {
error("Listen error: ");
return 1;
}
printf("Ready.\n");
struct sockaddr_in cliaddr;
socklen_t cliaddrlen = sizeof(cliaddr);
char response[512];
while (1) {
const int connfd = accept(sockfd, (struct sockaddr*) &cliaddr, &cliaddrlen);
if ( connfd == -1 ) {
printf("Accept error: %s\n", strerror(errno));
return 1;
}
const pid_t pid = fork();
if ( pid == -1 ) {
printf("Fork error: %s\n", strerror(errno));
continue;
}
if ( pid == 0 ) {
close(sockfd);
char buffer[16];
inet_ntop(AF_INET, &cliaddr.sin_addr, buffer, 16);
printf("Connection from %s accepted.\n", buffer);
while ( 1 ) {
int nread = read(connfd, response, 512);
if ( nread == -1 ) {
printf("%s\n", strerror(errno));
}
if (nread == 1 && response[0] == '\n') {
break;
}
write(connfd, response, nread);
//write(STDIN_FILENO, response, nread);
}
printf("Good bye!\n");
close(connfd);
return 0;
}
close(connfd);
wait(NULL);
}
return 0;
}