C++ 请求数据http

切回C++啦~~ 好好干! 冲!

#include<iostream>
#include<String>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib")//加载网络编程静态库
using namespace std;

//解析URL https://www.baidu.com/
void ParseURL(string url, string& host, string& res)
{
    if (url.find("http://") != url.npos)
    {
        url = url.substr(7);
    }
    else if (url.find("https://") != url.npos)
    {
        url = url.substr(8);
    }
    
    size_t pos = url.find_first_of("/");
    host = url.substr(0, pos);
    //获取资源地址
    res = url.substr(pos);
    cout << "域名:" << host << endl;
    cout << "资源:" << res << endl;
}
int main(int argc, char* argv[])
{
    WSADATA wsdata;    //这个结构被用来存储 被WSAStartup函数调用后返回的 Windows Sockets数据
    WSAStartup(MAKEWORD(2, 2), &wsdata);//初始化网络编程能够使用的函数或方法等....初始化后,就可以创建套接字了  搜索对应的Socket库 这是使用2.2的版本

    //创建套接字
    SOCKET skt = socket(AF_INET, SOCK_STREAM, 0);
    if (skt == SOCKET_ERROR)
    {
        cout << "创建套接字失败.." << endl;
        return 0;
    }
    else
    {
        cout << "创建套接字成功.." << endl;
    }

    string host_url;//URL
    string host;//域名
    string res;//资源地址
    cout << "请输入URL:";
    cin >> host_url;
    ParseURL(host_url, host, res);//解析

    //设置要连接的服务器地址
    HOSTENT* ip = gethostbyname(host.c_str());//获取主机信息,里面包含IP地址

    //将IP地址绑定到套接字
    sockaddr_in address;
    memset(&address, 0, sizeof(sockaddr_in));
    address.sin_family = AF_INET;
    address.sin_port = htons(80);//上面的URL端口是80,一般http端口号是80,htons作用是将端口号主机字节序转换为网络字节序
    memcpy(&address.sin_addr, ip->h_addr, 4);//转换为4个字节的正规IP地址

    //连接服务器  
    int cflag = connect(skt, (SOCKADDR*)&address, sizeof(SOCKADDR));
    if (cflag == SOCKET_ERROR)
    {
        cout << "连接服务器失败.." << endl;
        return 0;
    }
    else
    {
        cout << "连接服务器成功.." << endl;
    }
    //准备发送给服务器,客户端需要的信息请求http://studentwebsite.cn/index.html
    string req = "";
    req += "GET " + res + " HTTP/1.1\r\n";
    req += "Host: " + host + "\r\n";
    req += "User-Agent:*\r\n";
    req += "Connection:Close\r\n";
    req += "\r\n";

    //给服务器发送信息
    size_t clen = send(skt, req.c_str(), req.length(), 0);

    //接受服务器返回的信息
    string info;//接受的信息
    char ch;//每次接受的信息
    int rlength = 0;//接受数据的总大小
    int rlen = recv(skt, &ch, 1, 0);//每次接受的数据大小
    rlength += rlen;
    while (rlen != 0 && rlen != SOCKET_ERROR)
    {
        info += ch;
        rlen = recv(skt, &ch, 1, 0);//每次接受的数据大小
        rlength += rlen;
    }

    //编码转换 防止在控制台显示乱码
    char* pszBuffer = new char[info.length() + 1];
    wchar_t* pszWideBuffer = new wchar_t[(info.length() + 1) * 2];
    memset(pszWideBuffer, 0, (info.length() + 1) * 2);
    memset(pszBuffer, 0, info.length() + 1);
    MultiByteToWideChar(CP_UTF8, 0, info.c_str(), info.length(), pszWideBuffer, (info.length() + 1) * 2);//将unicode编码,转换为宽字节
    WideCharToMultiByte(CP_ACP, 0, pszWideBuffer, wcslen(pszWideBuffer), pszBuffer, info.length() + 1, NULL, NULL);//将宽字节,转换为控制台编码
    info = pszBuffer;
    delete[] pszBuffer;
    delete[] pszWideBuffer;

    //显示信息
    cout << "客户端给服务器发送了:" << req.length() << "个字节" << endl;
    cout << "客户端请求的信息是:" << endl;
    cout << req << endl;
    cout << "服务器返回给客户端了:" << rlength << "个字节" << endl;
    //cout << info << endl;//在控制台打印从服务器请求到信息
    system("pause");
    return 0;
}

 

在VS2019中运行的,这边可能会运行不过哦

所以要在这里补一句_WINSOCK_DEPRECATED_NO_WARNINGS

 

 

结果!

 

 开心~~~~~

 

posted @ 2021-04-08 18:31  冰糖葫芦很乖  阅读(1228)  评论(0编辑  收藏  举报