2

我在 C 上的服务器/客户端有这个问题。如果我在 SIGINT 之后关闭服务器套接字,然后我尝试从客户端写这个关闭的连接,我必须在客户端生成 SIGPIPE 之前写两次. 它不应该立即生成吗?这是正常行为还是我需要解决的问题?这是我的代码。我正在通过 127.0.0.1 连接的同一台 PC 上的 ubuntu 上进行测试。

服务器.c

sigset_t set;
struct sigaction sign;
int sock_acc;
int sock;

void closeSig(){
    close(sock_acc);
    close(sock);
    exit(1);
}


int main(){
    sigemptyset(&set);
    sigaddset(&set, SIGINT);
    sig.sa_sigaction = &closeSig;
    sig.sa_flags = SA_SIGINFO;
    sig.sa_mask = set;
    sigaction(SIGINT, &sig, NULL);
    //other code to accept the connection from the client
    sigprocmask(SIG_UNBLOCK, &set, NULL);
    //write/read calls
}

客户端.c

void closeSigPipe(){
    close(ds_sock);
    printf("Stop...");
    exit(1);
}

int main(){
    sigpipe.sa_sigaction = &closeSigPipe;
    sigpipe.sa_flags = SA_SIGINFO;
    sigaction(SIGPIPE, &sigpipe, NULL);
    //other code to connect the server, and write/read calls
}

问题是当我使用 CTRL+C 关闭服务器终端时,从客户端对连接的第一次写入工作没有任何问题... perror("Error:"); 打印“成功”...

4

1 回答 1

3

TCP 协议没有为接收者提供一种方法来告诉发送者它正在关闭连接。当它关闭连接时,它会发送一个FIN段,但这只是意味着它已经完成发送,而不是它不能再接收。

发送方检测到连接已关闭的方式是它尝试发送数据,接收方发回一个RST段作为响应。但是写入套接字不会等待响应,它只是将数据排队并立即返回。信号在RST接收到时出现,这将是很短的时间。

您必须进行两次写入的原因可能是因为Nagle's Algorithm。为了避免过多的网络开销,TCP 尝试将短消息组合成一个单独的段。维基百科页面包含一些解决方法。

于 2014-10-31T00:47:51.787 回答