gpt4 book ai didi

c - 如何在 Linux 中重现接受错误

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:03:29 29 4
gpt4 key购买 nike

我正在学习 Unix 网络编程第 1 卷,我想在 Linux 中重现 RST 的接受错误。

  1. 服务器:调用socket()bind()listen()sleep(10)
  2. 客户端:调用 LINGERsocket()connect()setsockopt()close()return
  3. 服务器:调用accept()

我认为第 3 步会出现类似 ECONNABORTED 的错误,但不会。

我想知道为什么吗?

如果你能帮助我,我将不胜感激。

服务器代码如下:

#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdio.h>
#include <strings.h>
#include <unistd.h>

int main(int argc, char* argv[]) {
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in addr;

bzero(&addr, sizeof addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(6666);
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);

bind(sock, (struct sockaddr*)(&addr), (socklen_t)(sizeof addr));
listen(sock, 5);
sleep(10);

if (accept(sock, NULL, NULL) < 0)
perror("error");
else
printf("right");

return 0;
}

以下是客户端代码

#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdio.h>
#include <strings.h>
#include <unistd.h>

int main(int argc, char* argv[]) {
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in addr;

bzero(&addr, sizeof addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(6666);
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);

connect(sock, (struct sockaddr*)(&addr), (socklen_t)(sizeof addr));

struct linger ling;
ling.l_onoff = 1;
ling.l_linger = 0;
setsockopt(sock, SOL_SOCKET, SO_LINGER, &ling, sizeof ling);
close(sock);

return 0;
}

最佳答案

没有。我想你会得到一个空的但完整的连接(没有数据)。内核将管理完整的连接建立,然后它将立即获得一个 FIN 数据包(意思是 EOF,而不是重置)并将处理它(或等待用户空间进程关闭其一侧,将 FIN 发送到另一侧)对于连接中止,您需要重新启动客户端计算机(或服务器),不允许它发送 FIN 数据包(或在重新启动之前将其与网络断开连接)永远不会回答 ACK,因此您不会收到从 ACK 发送的 RST。

RST 数据包在双方之间存在某种状态不匹配时由内核自动发送。为了在正确的实现中发生这种情况,您必须强制这种状态不匹配(这就是为什么需要重启机器)

  • 在双方之间建立连接并停止(休眠)以确保在断开电缆之前连接处于 ESTABLISHED 状态。
  • 从网络上断开其中一个对等点的物理连接,因此您不允许其流量进入网络。
  • 重启机器,所有socket都处于IDLE状态。
  • 重新连接电缆。一旦等待的机器从 sleep 中醒来并再次开始发送数据包,它将从另一端接收到一个 RST 段,因为它已经重新启动并且 TCP 不知道该连接。

获取 RST 段的其他方法涉及错误的 TCP 实现,或破坏传输中的数据包(更改传输中的发送方或接收方序列号)

RST 数据包的目的不是为 TCP 添加功能,而是检测不当行为,因为不应该通过正确使用套接字来获得重置。 Listen 系统调用允许您在内核空间中保留资源,以允许用户空间进程在客户端尝试连接时准备处理连接。如果您按照您的意愿进行操作,您将获得没有数据但有效的连接,SO_LINGER 会在机器没有时间向每个机器发送数据包时强制丢失状态其他...但是正在连接,整个连接都在内核中处理,并且不会中止。

关于c - 如何在 Linux 中重现接受错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53276541/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com