zoukankan      html  css  js  c++  java
  • 使用C语言获取百度源代码

    使用C语言获取百度源代码

    当我在单机世界摸爬滚打数月时,我也跟着时代的潮流,正式的跨入了网络化编程时代。学习一项新技术,永远是一件令人兴奋的事情。但是,想要找到一个好的学习教程无疑是一件困难的事情,搜寻百度谷歌无数次,终于踏入了Winsock的大门,我会在学习Windows网络编程中的心得体会发布出来,供大家学习。因为我也是新手,如果在博文当中有什么错误的地方,还请各位高手大大提出来,以帮助本人改正错误。

      如果你原来学习过Winsock编程,那么看本篇文章将会非常轻松。如果没学过,也没关系,本篇博文将会详细讲解。OK,废话不多说,直接跳到主题。

      1.在我们使用任何winsock函数之前,必须要现在头文件中添加winsock2.h和ws2_32.lib文件。

    #include <winsock2.h>
    
    #pragma comment(lib, "ws2_32.lib")

    同时,我们要注意:winsock2.h头文件必须要放在windows.h头文件的上面,要不然编译的时候会出错。


      2.在我们调用任何winsock函数之前,还要必须通过WSAStartup函数完成对winsock服务的初始化。

    int WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData )

    (1)wVersionRequested:一个WORD(双字节)型数值,在最高版本的Windows Sockets支持调用者使用,高阶字节指定小版本(修订本)号,低位字节指定主版本号。一般使用MAKEWORD(2,2)

    (2)lpWSAData 指向WSADATA数据结构的指针,用来接收Windows Sockets实现的细节。


      3.当我们调用了WSAStartup函数后,便可以调用其他的winsock函数了。使用WSASocket函数创建一个与指定服务提供者捆绑的套接字。

    WSASocket(int af, int type, int protocol, LPWSAPROTOCOL_INFOW lpProtocolInfo, GROUP g, DWORD dwFlags);

    (1)af:一个地址族规范,我们使用AF_INET。

    (2)type:新套接字的类型描述,我们使用SOCK_STREAM,也就是使用TCP

    (3)protocol:套接字使用的特定协议,如果调用者不愿指定协议则定为0

    (4)lpProtocolInfo:一个指向PROTOCOL_INFO结构的指针,该结构定义所创建套接口的特性。如果本参数非零,则前三个参数(af, type, protocol)被忽略。

    (5)g:保留给未来使用的套接字组。套接口组的标识符。

    (6)dwFlags:套接口属性描述。

    一般我们都是用前面三个,后面的都为NULL。如果成功,返回的是一个SOCKET类型的套接字。如果返回失败,则返回SOCKET_ERROR


      4.我们使用connect函数连接上我们指定的网站。

    connect(SOCKET s, const struct sockaddr FAR * name, int namelen);

    (1)s:套接字描述符,也就是我们调用的WSASocket函数返回的套接字

    (2)name:一个SOCKADDR类型,不过我们一般使用SOCKADDR_IN类型,也就是是我们需要连接的IP,端口等等

    (3)namelen:SOCKADDR结构体的长度。

    复制代码
    SOCKADDR_IN ipconfig;
    HOSTENT * iphost;
    char * url = "baidu.com";
    
    if((iphost = gethostbyname(url)) != NULL)
        ipconfig.sin_addr.S_un.S_addr = inet_addr(inet_ntoa(*((struct in_addr *)iphost->h_addr_list[0])))
    ipconfig.sin_port = htons(80);
    ipconfig.sin_family = AF_INET;
    复制代码

    可以看我的另外一篇博文:使用C语言获取指定域名的IP


      5.当我们连接以后,就需要发送http协议头信息了,如下:

    char * httpHeader = "GET /index.html\r\nAccept: application/javascript, */*;q=0.8\r\nHost: baidu.com\r\nConnection: Keep-Alive\r\n\r\n"

    然后使用send函数将其发送给主机。

    send(sock, httpHeader, strlen(httpHeader) + 1, 0)

      6.如果我们发送出去以后,需要使用recv函数进行接收从服务器返回过来的信息,其中,第一次返回的是服务器返回过来的HTTP头,我们可以从中看见是否成功,其后返回过来的则是网页的源代码:

    复制代码
    int i = 0, check, err = 0;
    char recvChar[100];
    char recvCDa[500];
    
    if(recv(sock, recvCDa, 500, 0) == SOCKET_ERROR)
        {
            fprintf(stderr, "返回信息失败,错误代码:%d",WSAGetLastError());
    
            system("pause");
            return 1;
        }
         printf("服务器返回HTTP头:%s\n", recvCDa);
    
         memset(recvChar, '\0', 101);
    
         while((check = recv(sock, recvChar, sizeof(recvChar), 0)) != SOCKET_ERROR)
        {
            if(check < 100)
                err = 1;
            printf("%s", recvChar);
    
            memset(recvChar, 0, 100);
    
            if(err == 1)
                break;
            i++;
        }
    复制代码

    OK,下面附上一段整体的获取百度源代码的代码:

    复制代码
    #include <stdio.h>
    #include <string.h>
    #include <winsock2.h>
    #include <Windows.h>
    
    #pragma comment(lib, "ws2_32.lib")
    
    using namespace std;
    
    char * urlIp(char * url);
    
    int main(int argc, char * argv[])
    {
        SOCKADDR_IN url_ipconfig = {sizeof(SOCKADDR_IN)};
        char * sendChar;
        WSADATA wsaDa;
        SOCKET sock;
        char ip[20];
        char sendString[100];
        char recvChar[100];
         char recvCDa[500];
    
        if(WSAStartup(MAKEWORD(2,2), &wsaDa) == SOCKET_ERROR)
        {
            fprintf(stderr, "初始化WSAStartup出错,错误代码:%d",WSAGetLastError());
    
            system("pause");
            return 1;
        }
    
        if((sock = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, NULL, 0)) == SOCKET_ERROR)
        {
            fprintf(stderr, "初始化WSAStartup出错,错误代码:%d",WSAGetLastError());
    
            system("pause");
            return 1;
        }
        
        strcpy(ip, urlIp("baidu.com"));
    
        url_ipconfig.sin_family = AF_INET;
        url_ipconfig.sin_port = htons(80);
        url_ipconfig.sin_addr.S_un.S_addr = inet_addr(ip);
    
        if(connect(sock, (SOCKADDR *)&url_ipconfig, sizeof(url_ipconfig)) == SOCKET_ERROR)
        {
            fprintf(stderr, "连接服务器失败,错误代码:%d",WSAGetLastError());
    
            system("pause");
            return 1;
        }
    
        strcpy(sendString, "GET /index.html HTTP/1.1\r\nAccept: application/javascript, */*;q=0.8\r\nHost: baidu.com\r\nConnection: Keep-Alive\r\n\r\n");
    
        if(send(sock, sendString, strlen(sendString) + 1, 0) == SOCKET_ERROR)
        {
            fprintf(stderr, "发送GET包失败失败,错误代码:%d\n",WSAGetLastError());
    
            system("pause");
            return 1;
        }
    
         memset(recvCDa, '\0', 500);
    
         if(recv(sock, recvCDa, 500, 0) == SOCKET_ERROR)
        {
            fprintf(stderr, "返回信息失败,错误代码:%d",WSAGetLastError());
    
            system("pause");
            return 1;
        }
         printf("%s\n", recvCDa);
    
         int i = 0, check, err = 0;
         memset(recvChar, '\0', 101);
    
         while((check = recv(sock, recvChar, sizeof(recvChar), 0)) != SOCKET_ERROR)
        {
            if(check < 100)
                err = 1;
            printf("%s", recvChar);
    
            memset(recvChar, 0, 100);
    
            if(err == 1)
                break;
            i++;
        }
        system("pause");
        return 0;
    }
    
    char * urlIp(char * url)
    {
        HOSTENT * iphost;
        char ipconfig[20];
        char ip[20];
    
        if((iphost = gethostbyname(url)) != NULL)
        {
            memcpy(&ip, inet_ntoa(*((struct in_addr *)iphost->h_addr_list[0])), 20);
        }
    
        return ip;
    }
    复制代码
    转载本文请注明来源:http://www.cnblogs.com/cnlyml。谢谢
     
    分类: Windows编程
  • 相关阅读:
    Asp.net中文本框全选的实现
    如何在Sql Server中读取最近一段时间的记录,比如取最近3天的或最近3个月的记录。
    asp.net存储过程分页+GridView控件 几百万数据 超快
    Gridview各种功能+AspNetPager+Ajax实现无刷新存储过程分页 (留着用)
    asp.net导出EXCEL的好方法!(好用,导出全部数据)
    GridView分页的实现 ASP.NET c#(转)特好用
    asp.net c# repeater或gridview导出EXCEL的详细代码。
    c#实现word,excel转pdf代码及部分Office 2007文件格式转换为xps和pdf代码整理
    C# WORD操作实现代码(转载)
    如何提高程序员的生产率 (2)
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2951998.html
Copyright © 2011-2022 走看看