代码之家  ›  专栏  ›  技术社区  ›  Andrew Y

为什么单独的getaddrinfo-like()+connect()不能通过_name()重构为(理论上的)connect_?

  •  1
  • Andrew Y  · 技术社区  · 15 年前

    我看到的大多数使用TCP的应用程序,大致执行以下操作以连接到远程主机:

    1. 从配置/用户输入(文本)中获取主机名(或地址)
    2. 将主机名解析为地址并添加端口,或者使用getaddrinfo()。
    3. 从上面,用其中一个远程地址填充sockaddr_*结构
    4. 使用connect()将套接字连接到远程主机。
    5. 如果失败,可能转到(3)并重试-或者只是抱怨错误。

    (2)在stock library实现中是阻塞的,(4)似乎是最常见的非阻塞的,这似乎为许多类似但不同的代码留出了空间,这些代码用于通过其主机名异步连接到远程主机。

    因此,问题是:不进行如下附加单次呼叫的好理由是什么?

    int sockfd = connect_by_name(const char *hostname, const char *servicename)
    

    ?

    我可以想出三个:

    • 历史:因为这就是API
    • 为地址选择/连接重试提供自定义的每个应用程序策略机制:这似乎有点肤浅,因为对于常见情况(“给我一个管道与远程主机对话”),底层操作系统应该更清楚
    • 向用户提供有关所涉及的具体步骤的视觉反馈(“名称解析”与“连接尝试”):这似乎很重要,查找+连接尝试可能需要一些时间

    只有最后一个看起来足够令人信服,可以重写每个客户端应用程序的resolve/connect代码(而不是至少拥有并使用一个广泛使用的库,除了现有的sockets api外,该库还可以实现connect-by-name()语义),所以肯定还有其他原因让我遗漏了?

    (问题背后的一个原因是,这种API似乎有助于IPv6以及其他流传输协议的可移植性)

    或者,也许存在这样一个图书馆,而我的google fu却让我失望了?

    (编辑:将定义修改为 意味 看,谢谢你的邀请3)

    3 回复  |  直到 15 年前
        1
  •  1
  •   caf    15 年前

    在标准库的约束内实现这样一个具有非阻塞特性的API(至关重要的是,它不应该启动自己的线程或进程来异步工作),这将是一个问题。

    进程的名称查找和连接部分都需要等待远程响应。如果其中任何一个不阻塞,那么这就需要一种非同步工作的方式,并向调用应用程序发送套接字状态变化的信号。 connect 能够做到这一点,因为 连接 调用在内核中完成,当连接完成时,内核可以将套接字标记为可读的。但是,名称查找是 之所以能够这样做,是因为名称查找的工作是在用户空间中完成的,而且不需要启动新的线程(标准库中的原话),给这个名称查找代码一个唤醒以继续工作的方法是一个困难的问题。

    能够 把你提议的电话回电 文件描述符-一个用于套接字本身,另一个用于告诉您“做” 没有什么 除了定期检查文件描述符是否可读之外。如果此文件描述符变得可读,请调用 cbn_do_some_more_work(fd) “。这显然是一个相当令人不快的API!

    通常的Unix方法是提供一组简单、灵活的工具,用于处理一组小的对象类型,这些类型可以组合在一起以产生复杂的效果。这和标准shell工具一样适用于编程API。

        2
  •  1
  •   R Samuel Klatchko    15 年前

    因为您可以构建更高级别的API,比如您在本地低级别API之上建议的API。

    socket api不仅适用于TCP,还可用于其他可能具有不同端点约定的协议(即只有名称且没有服务的Unix本地协议)。或者考虑使用套接字实现自身的DNS。如果连接代码依赖于DNS,那么DNS代码如何连接到服务器?

    如果您想要更高级别的抽象,那么要签出的一个库是 ACE .

        3
  •  1
  •   bortzmeyer    15 年前

    你的问题有几个问题。例如,为什么不呢 用这样的标准化API connect_by_name ?那当然可以 做个好主意。它不适合所有用途(请参阅DNS示例 来自R Samuel Klatchko)但是对于典型的网络程序,它会 没事。探索这种API的论文是” Simplifying Internet Applications Development With A Name-Oriented Sockets Interface “克里斯汀·沃格特。注释 这种API的另一个困难是“回调” 应用程序,例如请求回拨的SIP客户机: 应用程序不容易知道自己的名称,因此经常 尽管有问题,还是喜欢按地址回电,因为 具有nat的实例。

    现在,另一个问题是“有没有可能建立这样的 按名称连接 今天是子程序吗?”部分是的(有警告 CAF提到),但是,如果用用户空间编写,则 库,它不会完全“面向名称”,因为Unix 内核仍然使用IP地址管理连接。例如, 我期待一个“真实的” 连接程序名 例行程序能够 在重新编号之后(例如,因为移动主机重新编号, 这在用户空间很难做到。

    最后,是的,它已经存在很多类似的库 语义学。对于HTTP客户机(最常见的情况是 网络能力不是主要功能,例如XML 处理器),你有 Neon libcURL .用libcurl,你可以 简单地写下如下内容:

    #define URL "http://www.velib.paris.fr/service/stationdetails/42"
    ...
    curl_easy_setopt(curl, CURLOPT_URL, URL);
    result = curl_easy_perform(curl);
    

    哪一层比 连接程序名 因为它使用 URL,不是域名。