【问题标题】:Would like to evaluate a comparison between two sockaddr_in structs想要评估两个 sockaddr_in 结构之间的比较
【发布时间】:2015-03-20 22:39:13
【问题描述】:

目前我正在构建一个点对点网络架构,并且正处于创建接收函数的阶段,该函数将接收来自网络上多个客户端的消息。本质上,当调用 recvfrom 函数时 - 最近向主客户端发送消息的客户端的地址被加载到名为 fromAddr 的 sockaddr_in 结构中。然后,该程序被设计为遍历包含客户端类的多个实例的向量(每个实例都包含代表网络上客户端的必要信息和功能),并找到其 sockaddr_in 结构与刚刚接收到的匹配的客户端实例信息。在程序中,目前的评估是这样的:

void UDPClass::checkID(Message* mess, sockaddr_in fraeAddress)
{
sockaddr_in anAddr;
//Iterate through the vector of clients and find the one who sent the message
for(int i = 0; i < theClients.size(); i++)
{
    anAddr = theClients[i].getAddress();
    //if the address of the recieved message matches the address of the current client
    if((anAddr.sin_addr == fraeAddress.sin_addr) && (anAddr.sin_port == fraeAddress.sin_port))
    {
        //Update local instance of the client so that its location data matches that of the recieved message
        theClients[i].setX(mess->x);
        theClients[i].setY(mess->y);
    }
}
}

程序编译时报如下错误:

错误 3 错误 C2678:二进制“==”:未找到采用“IN_ADDR”类型左侧操作数的运算符(或没有可接受的转换)

正如可能推断的那样,我也尝试通过简单地比较两个 sockaddr_in 结构本身来评估表达式:

if(anAddr == fraeAddress)

报告相同的错误。问题是:如果没有创建一个带有重载运算符函数的 sockaddr_in 类来允许您评估表达式,那么实现这种比较的最简单方法是什么?

【问题讨论】:

  • 听起来像memcmp() 会帮助你。仅仅比较像 if(anAddr == fraeAddress) 这样的指针并没有多大帮助。
  • 运算符重载

标签: c++ network-programming p2p winsock2 sockaddr-in


【解决方案1】:

您可能希望像这样测试 in_addr 的无符号长成员:

if((anAddr.sin_addr.s_addr == fraeAddress.sin_addr.s_addr) && (anAddr.sin_port == fraeAddress.sin_port))

或对于 Windows:

if((anAddr.sin_addr.S_addr == fraeAddress.sin_addr.S_addr) && (anAddr.sin_port == fraeAddress.sin_port))

【讨论】:

  • 谢谢 - in_addr 结构中显然包含许多变量,但将比较每个 in_addr 的 ulong 变量等同于比较实际 IP 地址 - 我怀疑 IP 地址包含在 4 个 uchar 变量中。不过,我会给你一个方法。
  • 这四个 uchar 与 ulong (Microsoft) 合并,因此 unsigned long 占用的空间与它们相同。
【解决方案2】:

根据您的地址的确切来源,在某些情况下字节比较不起作用:IPv4 地址可能存储在sockaddr_insockaddr_in6 中。 sockaddr_in6 可能包含也可能不包含 sin6_scope_idsin6_flowinfo,并且对齐方式可能会有所不同。

您只需要 IPv4 和 IPv6,还是需要处理其他类型的套接字? (现在编写纯 IPv4 程序是不可原谅的。)如果是这样(并且也许你确实需要支持 unix、netlink、raw 或模糊套接字类型),我建议转换所有 IP地址转换为 IPv6,然后使用您自己的类进行比较。

(你也不应该使用线性搜索)。

【讨论】:

  • 这个框架纯粹是一个学术练习,所以在这种情况下使用 IPv6 并不是那么必要,但无论如何感谢。尽管搜索是线性的,但我打算最终让 recieve 函数在一个线程上运行。
  • @Enchanter 在纯粹的学术练习中,正确地做这些事情更为重要。而且使用每个套接字一个线程是一个糟糕的设计,您最多需要每个 CPU 一个线程来实现负载平衡。
  • 哦,同意做正确的事情很重要,例如每个套接字不使用一个线程 - 每个函数一个线程 - 在一个函数中迭代所有客户端并向它们连续发送更新数据包和一个线程接收数据包并相应地持续更新本地存储的客户端。每个核心有一个线程可能更好——每个 CPU 一个线程意味着整体有一个线程——你有一个 CPU 包含许多能够同时运行一个线程的核心。
  • @Enchanter 我在软件领域使用典型术语,例如引用 cpuset(7):“系统的 CPU 包括进程可以在其上执行的所有逻辑处理单元,包括(如果存在)包中的多个处理器内核和处理器内核中的超线程。”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-31
  • 2013-01-04
  • 1970-01-01
  • 2013-02-18
相关资源
最近更新 更多