【问题标题】:Invoke web page from Linux C从 Linux C 调用网页
【发布时间】:2010-05-04 22:21:46
【问题描述】:

我需要将所有 HTML 文本从像 http://localhost/index.html 这样的 url 读入 C 中的字符串。

我知道如果我输入 telnet -> telnet www.google.com 80 Get webpage.... 它会返回所有的 html。

如何在使用 C 的 linux 环境中执行此操作?

【问题讨论】:

  • 你知道多少C?事实上,你说String variable on C 表示不多:/
  • 忘记把它放在一个字符串中。你在 Linux 上,所以...int main(){system("curl http://localhost/index.html");}

标签: c linux http networking


【解决方案1】:

我建议使用几个库,它们通常在大多数 Linux 发行版上都可用:

libcurl 和 libxml2

libcurl 提供了一套全面的 http 特性,而 libxml2 提供了一个用于解析 html 的模块,称为 HTMLParser

希望能指引你正确的方向

【讨论】:

  • iu 试图运行 libcurl,但我不知道如何编译它。在我发现我犯了很多错误之后,这就是为什么我想尝试使用套接字。
  • 哎哟。我刚刚阅读了您关于从 C/Linux 使用 WCF 数据服务的评论。我认为您的问题与最初的问题似乎要问的问题更大,或者至少有所不同。它是作为 SOAP 公开的 WCF 服务吗?也许您应该确保将您的 WCF 服务公开为“普通”SOAP 服务(与任何专有的 MS 协议相反),然后将您的客户端引用到 C SOAP 实现,例如 sourceforge.net/projects/csoap
  • 嗨,我正在使用一个名为数据服务的 WCF 版本,它有一个名为 OData 的开放协议,这就是为什么我认为我不必使用肥皂,只需向网络发送一个请求。
【解决方案2】:

下面是一个粗略的代码大纲(即没有太多的错误检查,我没有尝试编译它)来帮助你入门,但是使用http://www.tenouk.com/cnlinuxsockettutorials.html 来学习套接字编程。如果您需要将主机名(如 google.com)转换为 IP 地址,请查找 gethostbyname。此外,您可能需要做一些工作来解析 HTTP 响应中的内容长度,然后确保继续调用 recv 直到获得所有字节。

#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>

void getWebpage(char *buffer, int bufsize, char *ipaddress)
{
    int sockfd;
    struct sockaddr_in destAddr;

    if((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1){
        fprintf(stderr, "Error opening client socket\n");
        close(sockfd);
        return;
    }

    destAddr.sin_family = PF_INET;
    destAddr.sin_port = htons(80); // HTTP port is 80
    destAddr.sin_addr.s_addr = inet_addr(ipaddress); // Get int representation of IP
    memset(&(destAddr.sin_zero), 0, 8);

    if(connect(sockfd, (struct sockaddr *)&destAddr, sizeof(struct sockaddr)) == -1){
        fprintf(stderr, "Error with client connecting to server\n");
        close(sockfd);
        return;
    }

    // Send http request
    char *httprequest = "GET / HTTP/1.0";
    send(sockfd, httprequest, strlen(httprequest), 0);
    recv(sockfd, buffer, bufsize, 0);

    // Now buffer has the HTTP response which includes the webpage. You can either
    // trim off the HTTP header, or just leave it in depending on what you are doing
    // with the page
}

【讨论】:

  • 我试过这个,但是当点击 recv() 时它停止了。我认为是我传递给缓冲区和 bufsize 的参数。
  • recv 将阻塞等待来自套接字文件描述符的输入。查看linux.die.net/man/2/recv 了解更多关于如何使用recv 的信息。还要检查 send 的返回值以确保请求发送正常。
【解决方案3】:

如果你真的不想搞乱套接字,你总是可以创建一个命名的临时文件,分叉一个进程并 execvp() 它运行 wget -0 ,然后从该临时文件中读取输入。

虽然这将是一种非常蹩脚且效率低下的方式,但这意味着您不必搞乱 TCP 和发送 HTTP 请求。

【讨论】:

  • 对不起,我没明白你的意思。
  • @umetzu:在 .Net 术语中,如果您使用预构建的解决方案,例如可以获取 HTML 内容并将其写入文件的应用程序 wget(控制台应用程序),则可以跳过套接字您可以从您的应用程序中读取。从您的应用启动 wget,等待进程退出,读取文件。
【解决方案4】:

您使用套接字,使用 HTTP 询问 Web 服务器(其中有“http://localhost/index.html”),然后解析您收到的数据。

如果您是套接字编程的初学者,对您有帮助:http://beej.us/guide/bgnet/

【讨论】:

  • 你有什么简单的例子可以做到这一点吗?我要上网查一下。
  • @umetzu:这不是一个简单的任务,所以很难写一个简单的例子。
  • @Cri 不相信我的网络服务器曾被审问过,哈哈
【解决方案5】:

假设您知道如何将文件读入字符串,我会尝试

const char *url_contents(const char *url) {
  // create w3m command and pass it to popen()
  int bufsize = strlen(url) + 100;
  char *buf = malloc(bufsize);
  snprintf(buf, bufsize, "w3m -dump_source '%s'");

  // get a file handle, read all the html from it, close, and return
  FILE *html = popen(buf, "r");
  const char *s = read_file_into_string(html); // you write this function
  fclose(html);
  return s;
}

您创建一个进程,但让w3m 完成繁重的工作要容易得多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-17
    • 2018-12-09
    • 1970-01-01
    • 2016-02-08
    • 2017-01-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多