【问题标题】:STARTED getting RST packet from client socket after I replied SYN packet with SYN + ACK packet在我用 SYN + ACK 数据包回复 SYN 数据包后,开始从客户端套接字获取 RST 数据包
【发布时间】:2021-12-30 09:05:22
【问题描述】:

我正在创建一个简单的 TCP 模拟程序,它可以作为一个简单的 IP 上的 TCP 服务器,问题出在我收到 SYN 数据包时编写的代码中,--> 我在我的程序服务器中完成了所有响应数据包的制定,并且创建响应包并使用 SYN+ACK 包进行回复。

但是在我回复 SYN+ACK 数据包后,我从客户端套接字获得了 RST 数据包。我不知道我的 TCP 有什么问题,或者某些头文件使我的客户端套接字只能用 RST 数据包回复我的 SYN+ACK 数据包。

我在网上看到关于 RST 数据包的信息,它说 RST 在主机上收到有两个原因,但可能还有更多原因

There are a few circumstances in which a TCP packet might not be expected; the two most common are:

    The packet is an initial SYN packet trying to establish a connection to a server port on which no process is listening.
    The packet arrives on a TCP connection that was previously established, but the local application already closed its socket or exited and the OS closed the socket.

所以我想知道在我的案例中给出的原因是什么。

当我在程序 IP 套接字上收到 SYN 数据包时

0000   45 00 00 3c 81 37 40 00 40 06 24 11 c0 a8 0a 14
0010   c0 a8 0a 0f ba 50 00 50 15 1a 68 41 00 00 00 00
0020   a0 02 fa f0 a3 ce 00 00 02 04 05 b4 04 02 08 0a
0030   de d7 fc f8 00 00 00 00 01 03 03 07

我用 SYN+ACK 包回复。我的 TCP 数据包是这样的

0000   45 00 00 28 00 64 40 00 40 06 a4 f8 c0 a8 0a 0f
0010   c0 a8 0a 14 00 50 ba 50 00 01 00 00 15 1a 68 41
0020   50 12 fa f0 e7 70 00 00

因此,TCP 中的字段类似于上面的 20(IP 标头)+20(TCP 标头)字节的数据包(SYN+ACK),用于从我的代码回复客户端套接字的 SYN+ACK。但不是从客户端开始发送数据,而是我的客户端开始发送 RST 数据包,在我的代码中,当我将 SYN + ACK 数据包从我的代码发送到客户端套接字后,我立即收到 RST 数据包。

但是,我得到 RST 数据包(重置数据包)而不是从客户端获取一些数据,或者至少我的客户端套接字 [connect()] 函数调用成功了?如何使来自我的客户端发送的这个 RST 数据包消失,以便我的客户端最终开始发送数据并且我的服务器代码开始获取数据?我做错了什么?

【问题讨论】:

  • 将 ACK 设置为 SYN + 1 中的序列号的代码发生了什么?您收到带有 SEQ 15 1a 68 41 的 SYN 数据包,并使用带有 ACK 15 1a 68 41 的 SYNACK 回复。这看起来不像 SEQ+1。

标签: c sockets tcp


【解决方案1】:

我看不出这个数据包本身有什么问题,但是这个数据包必须在 SYN 的上下文中。 SYN+ACK中ACK的预期序列号是SYN的序列号(ISN,即初始序列号)加1。

但是,ACK 不是 ISN+1,而是来自接收到的 SYN 的简单 ISN。这意味着 SYN+ACK 出现故障,从而导致 RST。

【讨论】:

  • if the ACK in your packet does not fit the sequence number in the received SYN. 你是说我的 SYN + ACK 数据包的序列号错误。如果我收到 SYN 数据包,你能告诉我 SYN + ACK 回复数据包的序列号应该是多少。我尝试将收到的 SYN 的序列号分配给我的 SYN + ACK 在回复数据包中的确认号,但我的客户仍然给我 RST 标志
  • @user786:请编辑您的问题以添加 SYN,就像您在 Network Engineering 的(已关闭)帖子中所做的那样。至于序列号应该如何 - 参见例如media.geeksforgeeks.org/wp-content/uploads/TCP-connection-1.png
  • 问题用 SYN 数据包更新。你能看看吗
  • @user786:查看更新的答案。
【解决方案2】:

发送RST的一般原因是接收方找不到套接字,应该将传入的数据包归因于。

常见情况包括:

  • 端口不匹配:端口对没有打开的套接字
  • 序列号不匹配:ACK 号不正确,或者 ACK 号不适合发送方的窗口(这里发送方是接收到 ACK 的一方,因为 ACK 是对发送方发送内容的响应)

根据 TCP 规范,设置了 SYN(以及 FIN)标志的数据包在确认时 ACK 号加一,即好像这些标志占用了一个数据字节。


考虑到收到的SYN和发送的SYNACK,可以看到SYN中的序列号是15 1a 68 41,SYNACK中的ACK号也是15 1a 68 41,而不是应该的SYN + 1

P.S.:TCP 标头的结构可以在例如wikipedia 中找到。可以在this answer 中找到如何将数据包字节与标头字段匹配的说明。另外,发件人窗口的图示可以在here找到。

【讨论】:

  • or ACK number does not fit within sender's window (here sender is the side that has received an ACK, because ACK is a response to sender sending something) 所以我需要照顾发件人窗口。如何找到该发件人窗口。和tcp窗口一样吗?
  • Considering both received SYN and sent SYNACK, one can see, that sequence number in SYN is 15 1a 68 41 and ACK number in SYNACK is also 15 1a 68 41, which is not SYN + 1 as it should be. 所以如果我像这样tcp->ack_seq=htons(ntohs(tcph->seq)+1); 填写我的 SYN+ACK 数据包的确认号,这是正确的吗?但是有了这个,我收到的序列号没有增加到seq+1,然后被分配在我的代码中发送SYN ACK的确认号,你在你的答案wireshark中显示了
  • 不,接收器负责接收器窗口。但是,接收方需要发送正确的 ACK,以便发送方可以判断此 ACK 指的是哪个数据包。
  • tcp->ack_seq=htons(ntohs(tcph->seq)+1); 应该是正确的。但是,正如我在我们对您之前的问题的讨论中指出的那样,您已经调用了函数“fill_some_tcp”(或类似的东西)3 次,并在两次调用之间更改了标头的值。查看您的代码并检查您是否覆盖了此 tcp->ack_seq 值。
  • tcp->ack_seq=htons(ntohs(tcph->seq)+1); should be correct. 是的,我知道,或者至少听起来像,但我没有做对,因为这可能是错误的,它看起来是正确的,但 tcp->ack_seq=htons(ntohs(tcph->seq)+1); 存在本质上的错误,它可能是字节排序的玩他们的魔法什么的,真的让我发疯:stackoverflow.com/questions/70540996/…
猜你喜欢
  • 1970-01-01
  • 2018-08-25
  • 1970-01-01
  • 2017-10-12
  • 2020-04-24
  • 2014-03-04
  • 2018-06-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多