目前共有10篇帖子。 內容轉換:不轉換▼
 
點擊 回復
4612 9
【C程序】Linux下直接用套接字发送HTTP请求并获取HTML内容
一派護法 十九級
1樓 發表于:2016-2-13 21:14

【C程序文件:client.c】
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>

int main(void)
{
    // 建立套接字
    struct sockaddr_in addr;
    char buffer[1024];
    char *request;
    char *html;
    int i;
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1)
    {
        printf("socket error\n");
        exit(1);
    }
    printf("sockfd = %d\n", sockfd);
   
    // 连接到服务器
    addr.sin_family = AF_INET;
    addr.sin_port = htons(80); // 端口号
    addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 服务器IP地址
    bzero(addr.sin_zero, sizeof(addr.sin_zero));
    i = connect(sockfd, (struct sockaddr *)&addr, sizeof(addr));
    printf("connect = %d\n", i);
   
    // 发送HTTP请求
    request = "GET /test/simple.php HTTP/1.1\r\nHost: localhost\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: en-US,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\n\r\n";
    write(sockfd, request, strlen(request));
   
    // 读取服务器响应内容
    bzero(buffer, sizeof(buffer));
    i = read(sockfd, buffer, sizeof(buffer));
    printf("read = %d\n", i);
    puts("\nContent: ");
    puts(buffer);
   
    // 提取出HTML输出部分
    for (html = buffer + 4; *html != '\0' && strncmp(html - 4, "\r\n\r\n", 4) != 0; html++);
    printf("\nHTML(length=%ld): \n", strlen(html));
    puts(html);
   
    // 关闭套接字
    close(sockfd);
    return 0;
}
【Makefile】
client: client.c
    gcc client.c -o client
【PHP页面:/var/www/html/test/simple.php】
<?php
echo 'test<br>';
echo date('Y-n-j H:i:s');
?>
一派護法 十九級
2樓 發表于:2016-2-13 21:14

【运行结果】
octopus@pc3:~/Documents/Codes/C/socket$ ./client
sockfd = 3
connect = 0
read = 251

Content:
HTTP/1.1 200 OK
Date: Sat, 13 Feb 2016 12:02:41 GMT
Server: Apache/2.4.7 (Ubuntu)
X-Powered-By: PHP/5.5.9-1ubuntu4.14
Content-Length: 26
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html

test<br>2016-2-13 20:02:41

HTML(length=26):
test<br>2016-2-13 20:02:41
octopus@pc3:~/Documents/Codes/C/socket$
一派護法 十九級
3樓 發表于:2016-2-13 21:14

如果获取的内容不是HTML网页而是一个PNG图像,要保存成文件也很简单:
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>

#define BUF_LEN 10240

void savepng(char *filename, char *data, int length)
{
    FILE *fp = fopen(filename, "w");
    fwrite(data, length, 1, fp);
    fclose(fp);
}

int main(void)
{
    // 建立套接字
    struct sockaddr_in addr;
    char *buffer = (char *)malloc(BUF_LEN);
    char *request;
    char *data;
    int n;
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1)
    {
        printf("socket error\n");
        exit(1);
    }
    printf("sockfd = %d\n", sockfd);
   
    // 连接到服务器
    addr.sin_family = AF_INET;
    addr.sin_port = htons(80); // 端口号
    addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 服务器IP地址
    bzero(addr.sin_zero, sizeof(addr.sin_zero));
    n = connect(sockfd, (struct sockaddr *)&addr, sizeof(addr));
    printf("connect = %d\n", n);
   
    // 发送HTTP请求
    request = "GET /icons/ubuntu-logo.png HTTP/1.1\r\nHost: localhost\r\nAccept: image/png\r\nAccept-Language: en-US\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\n\r\n";
    write(sockfd, request, strlen(request));
   
    // 读取服务器响应内容
    bzero(buffer, sizeof(buffer));
    n = read(sockfd, buffer, BUF_LEN);
    printf("read = %d\n", n);
    puts("\nContent: ");
    puts(buffer);
   
    // 提取出PNG部分并保存为文件
    for (data = buffer + 4; *data != '\0' && strncmp(data - 4, "\r\n\r\n", 4) != 0; data++);
    savepng("image.png", data, n - (data - buffer));
   
    // 关闭套接字
    close(sockfd);
    free(buffer);
    return 0;
}
一派護法 十九級
4樓 發表于:2016-2-13 21:20

顺便把Windows平台下的C++代码也发上来:
// DownloadPNG.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include <fstream>
#include <iostream>
using namespace std;

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

#define BUF_LEN 10240

int _tmain(int argc, _TCHAR* argv[])
{
    WSADATA wsd;
    WSAStartup(MAKEWORD(2, 2), &wsd);

    SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
    sockaddr_in addr;
    addr.sin_addr.S_un.S_addr = inet_addr("192.168.0.4");
    addr.sin_family = AF_INET;
    addr.sin_port = htons(80);
    ZeroMemory(addr.sin_zero, sizeof(addr.sin_zero));
    int i = connect(sock, (sockaddr *)&addr, sizeof(addr));
    cout << "connect: " << i << endl;

    if (i == 0)
    {
        char *request = "GET /icons/ubuntu-logo.png HTTP/1.1\r\nHost: localhost\r\nAccept: image/png\r\nAccept-Language: en-US\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\n\r\n";
        send(sock, request, strlen(request), NULL);

        char *buffer = new char[BUF_LEN];
        int size = recv(sock, buffer, BUF_LEN, NULL);
        cout << size << " bytes received" << endl;
        char *data;
        for (data = buffer + 4; strncmp(data - 4, "\r\n\r\n", 4) != 0; data++);
        ofstream file("image.png", ios::binary);
        file.write(data, size - (data - buffer));
        file.close();
        free(buffer);
    }
    else
        cout << "连接失败" << endl;

    closesocket(sock);
    WSACleanup();
    system("pause");
    return 0;
}


一派護法 十九級
5樓 發表于:2016-2-13 21:27

回復4樓 @巨大八爪鱼 的內容:
顺便把Windows平台下的C++代码也发上来:
// DownloadPNG.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"...
那个free(buffer);写错了,应该是delete[] buffer;
一派護法 十九級
6樓 發表于:2016-2-13 23:05

Windows下从网络加载图片到内存中并立即显示到窗口上,不保存到磁盘:
#include <Windows.h>

#include <gdiplus.h>
#pragma comment(lib, "gdiplus.lib")
using namespace Gdiplus;

#pragma comment(lib, "ws2_32.lib")

#define BUF_LEN 10240
Bitmap *image;

void download(void)
{
    WSADATA wsd;
    WSAStartup(MAKEWORD(2, 2), &wsd);
    SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
    sockaddr_in addr;
    addr.sin_addr.S_un.S_addr = inet_addr("192.168.0.4");
    addr.sin_family = AF_INET;
    addr.sin_port = htons(80);
    ZeroMemory(addr.sin_zero, sizeof(addr.sin_zero));
    int i = connect(sock, (sockaddr *)&addr, sizeof(addr));

    if (i == 0)
    {
        char *request = "GET /icons/ubuntu-logo.png HTTP/1.1\r\nHost: localhost\r\nAccept: image/png\r\nAccept-Language: en-US\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\n\r\n";
        send(sock, request, strlen(request), NULL);

        char *buffer = new char[BUF_LEN];
        int size = recv(sock, buffer, BUF_LEN, NULL);
        char *data;
        for (data = buffer + 4; strncmp(data - 4, "\r\n\r\n", 4) != 0; data++);

        int pngsize = size - (data - buffer);
        HGLOBAL hMem = GlobalAlloc(GMEM_FIXED, pngsize);
        char *pData = (char *)GlobalLock(hMem);
        memcpy(pData, data, pngsize);
        delete[] buffer;
        GlobalUnlock(hMem);

        IStream *stream;
        CreateStreamOnHGlobal(hMem, TRUE, &stream);
        image = Bitmap::FromStream(stream);
        stream->Release();
    }

    closesocket(sock);
    WSACleanup();
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;

    switch (uMsg)
    {
    case WM_CREATE:
        download();
        break;
    case WM_DESTROY:
        delete image;
        PostQuitMessage(0);
        break;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        {
            Graphics graphics(hdc);
            graphics.DrawImage(image, 10, 10);
        }
        EndPaint(hWnd, &ps);
        break;
    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return FALSE;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    GdiplusStartupInput gdiplus;
    ULONG_PTR gdiToken;
    GdiplusStartup(&gdiToken, &gdiplus, NULL);

    WNDCLASS wc;
    wc.cbClsExtra = wc.cbWndExtra = 0;
    wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hInstance = hInstance;
    wc.lpfnWndProc = WndProc;
    wc.lpszClassName = "ShowPNG";
    wc.lpszMenuName = NULL;
    wc.style = NULL;
    RegisterClass(&wc);

    HWND hWnd = CreateWindow(wc.lpszClassName, "Show PNG", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
    if (!hWnd)
    {
        GdiplusShutdown(gdiToken);
        return 1;
    }
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    GdiplusShutdown(gdiToken);
    return msg.wParam;
}


一派護法 十九級
7樓 發表于:2016-2-14 15:06

int pngsize = size - (data - buffer);
IStream *stream = SHCreateMemStream((BYTE *)data, pngsize);
image = Image::FromStream(stream);
stream->Release();
在创建IStream对象时,可以直接使用char *数组,无需单独创建一个HGLOBAL句柄。
一派護法 十九級
8樓 發表于:2016-2-14 15:08

【Windows下的示例2】
#include <Windows.h>

#include <gdiplus.h>
#pragma comment(lib, "gdiplus.lib")
using namespace Gdiplus;

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

#pragma comment(lib, "ws2_32.lib")

#define BUF_LEN 20480
Image *image;

void download(void)
{
    WSADATA wsd;
    WSAStartup(MAKEWORD(2, 2), &wsd);
    SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
    sockaddr_in addr;
    addr.sin_addr.S_un.S_addr = inet_addr("192.168.0.4");
    addr.sin_family = AF_INET;
    addr.sin_port = htons(80);
    ZeroMemory(addr.sin_zero, sizeof(addr.sin_zero));
    int i = connect(sock, (sockaddr *)&addr, sizeof(addr));

    if (i == 0)
    {
        char *request = "GET /test/template/pngtest.png HTTP/1.1\r\nHost: localhost\r\nAccept: image/png\r\nAccept-Language: en-US\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\n\r\n";
        send(sock, request, strlen(request), NULL);

        char *buffer = new char[BUF_LEN];
        int size = recv(sock, buffer, BUF_LEN, NULL);
        char *data;
        for (data = buffer + 4; strncmp(data - 4, "\r\n\r\n", 4) != 0; data++);

        int pngsize = size - (data - buffer);
        IStream *stream = SHCreateMemStream((BYTE *)data, pngsize);
        image = Image::FromStream(stream);
        stream->Release();
    }

    closesocket(sock);
    WSACleanup();
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;

    switch (uMsg)
    {
    case WM_CREATE:
        download();
        break;
    case WM_DESTROY:
        delete image;
        PostQuitMessage(0);
        break;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        {
            Graphics graphics(hdc);
            graphics.DrawImage(image, 10, 10);
        }
        EndPaint(hWnd, &ps);
        break;
    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return FALSE;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    GdiplusStartupInput gdiplus;
    ULONG_PTR gdiToken;
    GdiplusStartup(&gdiToken, &gdiplus, NULL);

    WNDCLASS wc;
    wc.cbClsExtra = wc.cbWndExtra = 0;
    wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hInstance = hInstance;
    wc.lpfnWndProc = WndProc;
    wc.lpszClassName = "ShowPNG";
    wc.lpszMenuName = NULL;
    wc.style = NULL;
    RegisterClass(&wc);

    HWND hWnd = CreateWindow(wc.lpszClassName, "Show PNG", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
    if (!hWnd)
    {
        GdiplusShutdown(gdiToken);
        return 1;
    }
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    GdiplusShutdown(gdiToken);
    return msg.wParam;
}
一派護法 十九級
9樓 發表于:2016-2-17 23:35

在Windows系统下有专门的HTTP函数:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa384098%28v=vs.85%29.aspx
WinHttpOpen
一派護法 十九級
10樓 發表于:2016-2-17 23:48

回復帖子

內容:
用戶名: 您目前是匿名發表
驗證碼:
(快捷鍵:Ctrl+Enter)
 

本帖信息

點擊數:4612 回複數:9
評論數: ?
作者: 巨大八爪鱼
最後回復:巨大八爪鱼
最後回復時間:2016-2-17 23:48
 
©2010-2024 Arslanbar Ver2.0
除非另有聲明,本站採用創用CC姓名標示-相同方式分享 3.0 Unported許可協議進行許可。