如何从tcp段构建消息

时间:2010-10-21 21:03:44

标签: c# tcp message segment

在C#中工作,我使用SharpPCap从winpcap跟踪中获取段。

我需要重建该跟踪中发送和接收的所有消息。

在我的情况下,客户端和服务器的IP将永远不会相同。客户端口不一定会改变。

消息使用的协议可能是HTTP或我不知道的自定义。

这就是我目前的做法:

            if (ipPacket.Protocol == IPProtocolType.TCP)
            {
                TcpPacket tcpPacket = (TcpPacket)ipPacket.PayloadPacket;

                Packet dataPacket = tcpPacket;
                while (dataPacket.PayloadPacket != null)
                    dataPacket = dataPacket.PayloadPacket;

                if (dataPacket.PayloadData.Length > 0)
                {
                    if (m_MessageContainer.IsEmpty()
                        || ((m_MessageContainer.Last().SourceIp.ToString() != ipPacket.SourceAddress.ToString())
                             && tcpPacket.Psh))
                    {
                        m_MessageContainer.Add(BuildMessage(ipPacket, tcpPacket));                      
                    }
                    m_MessageContainer.Last().AddData(dataPacket.PayloadData);
                }
            }

我的解决方案的问题是客户端连续发送两个请求。我只将两个消息合并为一个。如果我改变

if (m_MessageContainer.IsEmpty()
  || ((m_MessageContainer.Last().SourceIp.ToString() != ipPacket.SourceAddress.ToString())
       && tcpPacket.Psh))
 {
     m_MessageContainer.Add(BuildMessage(ipPacket, tcpPacket));                      
 }

通过

if (m_MessageContainer.IsEmpty()
  || tcpPacket.Psh)
 {
     m_MessageContainer.Add(BuildMessage(ipPacket, tcpPacket));                      
 }

然后在多个tcp段之间拆分消息并且在至少两个tcp段上设置标志psh时会出现问题。

我需要一种方法来正确合并段以重建原始邮件。我不能依赖TCP上使用的协议。

谢谢!

修改: 在wireshark中,当你遵循tcp流时,它不一定知道tcp上的协议,但它能够以不同的颜色显示每个请求和响应。它是如何做到的?我正在寻求相同的功能,因为在我的情况下,在流中收到响应之前永远不会有第二个请求。 谢谢

1 个答案:

答案 0 :(得分:0)

无法通过观察线路上的流来了解原始应用程序代码如何写入套接字。您正在谈论使用可能在某些情况下显示的提示,但您不能依赖它们(正如您所发现的那样)。

write(sock, "GET / HTTP/1.0\r\n\r\n", len);

write(sock, "GET / HTTP/1.0\r\n", len);
write(sock, "\r\n", 2);

write(sock, "GET / HTTP/1.0\r\n", len);
sleep(1);
write(sock, "\r\n", 2);

这三个示例都是编写HTTP查询的合法方法。所有三个在电线上看起来都一样。当然最后一个很有可能会有所不同,即使它意味着同样的事情(想象一下睡眠不明确,但可能是因为从磁盘上读取cookie)。即便如此,如果特定的TCP套接字在两次写入发生时通过重试被阻止,则最后一个可以折叠成单个传输。第二个示例可能仅基于接口上的其他负载(或CORK等套接字选项)显示为一个或两个数据包。