在前面的系列网络编程文章中,我们都是使用socket 自己实现客户端和服务器端来互相发数据测试,现在尝试使用socket 客户端发

送http 请求给某个网站,然后接收网站的响应数据。http 协议参考 这里

代码如下:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
 
#include<stdio.h>
#include<stdlib.h>
#include<string.h>    //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<netdb.h>
#include<errno.h>

int main(int argc , char *argv[])
{
    int socket_desc;
    struct sockaddr_in server;
    char *message;

//Create socket
    socket_desc = socket(AF_INET , SOCK_STREAM , 0);
    if (socket_desc == -1)
    {
        printf("Could not create socket");
    }

char ip[20] = {0};
    char *hostname = "www.google.com.hk";
    struct hostent *hp;
    if ((hp = gethostbyname(hostname)) == NULL)
        return 1;
    //  #define h_addr h_addr_list[0]
    strcpy(ip, inet_ntoa(*(struct in_addr *)hp->h_addr_list[0]));

server.sin_addr.s_addr = inet_addr(ip);
    server.sin_family = AF_INET;
    server.sin_port = htons( 80 );

//Connect to remote server
    if (connect(socket_desc , (struct sockaddr *)&server , sizeof(server)) < 0)
    {
        puts("connect error");
        return 1;
    }

puts("Connected\n");

//Send some data
    message = "GET /?st=1 HTTP/1.1\r\nHost: www.google.com.hk\r\n\r\n";
    if( send(socket_desc , message , strlen(message) , 0) < 0)
    {
        puts("Send failed");
        return 1;
    }
    puts("Data Send\n");

struct timeval timeout = {3, 0};
    setsockopt(socket_desc, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));

//Receive a reply from the server
    //loop
    int size_recv , total_size = 0;
    char chunk[512];
    while(1)
    {
        memset(chunk , 0 , 512); //clear the variable
        if((size_recv =  recv(socket_desc , chunk , 512 , 0) ) == -1)
        {
            if (errno == EWOULDBLOCK || errno == EAGAIN)
            {
                printf("recv timeout ...\n");
                break;
            }
            else if (errno == EINTR)
            {
                printf("interrupt by signal...\n");
                continue;
            }
            else if (errno == ENOENT)
            {
                printf("recv RST segement...\n");
                break;
            }
            else
            {
                printf("unknown error!\n");
                exit(1);
            }
        }
        else if (size_recv == 0)
        {
            printf("peer closed ...\n");
            break;
        }
        else
        {
            total_size += size_recv;
            printf("%s" , chunk);
        }
    }

printf("Reply received, total_size = %d bytes\n", total_size);

return 0;
}

输出如下:

.............................省略................................

从上面的输出可以看到有完整的<html> </html> ,即已经完整接收,但有一点不解的是为什么最后会接收到一个0?

Chunked transfer encoding uses a chunk size of 0 to mark
the end of the content.

程序中  struct timeval timeout = {3,0};

setsockopt(socket_desc, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));

设置超时时间为3s,现在recv 为阻塞接收,如果超时时间内接收缓冲区没有一点数据,则返回-1 且errno = EWOULDBLOCK 。

退出循环,程序结束。

在这里顺便提一下,recv的第四个参数如果设置为MSG_WAITALL,在阻塞模式下不等到指定数目的数据是不会返回的,除非超时时间到或者被信号打断。但在这里我们并不知道对方会发来具体多少数据,所以不能使用这种方法来读取数据,否则可能出现一直阻塞的情况。

注:在阻塞发送时,也有人喜欢设置发送超时,超时判断返回值,如果没有发送完整则继续发送。但实际上本身阻塞发送会一直阻

塞到发送完整才返回,好像二者并无大的区别。

socket 请求接收完整的一个http响应(设置recv 接收超时选项SO_RCVTIMEO)的更多相关文章

  1. 一个http请求的完整详细过程

    整个流程 域名解析: 与服务器建立连接:tcp连接: 发起HTTP请求: 服务器响应HTTP请求,浏览器得到html代码: 浏览器解析html代码,并请求html代码中的资源(如js.css.图片): ...

  2. 每次收到的 HTTP 请求,就可以打开一个 SqlSession,返回一个响应,就关闭它

    mybatis – MyBatis 3 | 入门 http://www.mybatis.org/mybatis-3/zh/getting-started.html 作用域(Scope)和生命周期 理解 ...

  3. Python Socket请求网站获取数据

     Python Socket请求网站获取数据 ---阻塞 I/O     ->收快递,快递如果不到,就干不了其他的活 ---非阻塞I/0 ->收快递,不断的去问,有没有送到,有没有送到,. ...

  4. WebService、Http请求、Socket请求

    WebService 定义 一种web程序访问方式,常见协议:SOAP(简单对象访问协议),其实就是Http+XML.利用对象进行数据交互. 请求方法 import lombok.extern.slf ...

  5. 对tomcat来说,每一个进来的请求(request)都需要一个线程,直到该请求结束。

    这段时间折腾了哈java web应用的压力测试,部署容器是tomcat 7.期间学到了蛮多散碎的知识点,及时梳理总结,构建良好且易理解的知识架构把它们组织起来,以备忘.对web应用开发者来说,我们很关 ...

  6. 支持JDK19虚拟线程的web框架,之二:完整开发一个支持虚拟线程的quarkus应用

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本篇是<支持JDK19虚拟线程的web ...

  7. node.js 针对不同的请求路径(url) 做出不同的响应

    边看这个边写的: http://wenku.baidu.com/link?url=C4yLe-TVH6060u_x4t34H3Ze8tjoL7HjJaKgH-TvHnEYl-T_gAMYwhmrCeM ...

  8. Asp.net 4.0,首次请求目录下的文件时响应很慢

    原文:Asp.net 4.0,首次请求目录下的文件时响应很慢 1. 问题起因2. 尝试过的处理思路3. 解决方法 1. 问题起因 一个从VS2003(.Net Framework 1.1)升级到.ne ...

  9. TCP socket 多线程 并发服务器(发送)与客户端(接收)

    实现功能:Ubuntu上通过多线程实现服务器并发给客户端发送文件,携带包头,根据包头信息命名新文件.适用于短连接. 问题小结: 01. 调用嵌套在结构体中的结构体char 数组成员时,需要动态分配内存 ...

随机推荐

  1. pytorch 学习问题

    https://pytorch.org/tutorials/beginner/blitz/neural_networks_tutorial.html#sphx-glr-beginner-blitz-n ...

  2. scala 学习笔记十 元组

    1.元组初始化 2.元组作为函数返回值 3.元组拆包 上面168行 ,单个val后面跟着一个由五个标识符构成的元组,表示对ff返回的元组进行拆包 上面174行,将整个元组捕获到单个val或var中,那 ...

  3. [mysql] C++操作mysql方法总结(1)

    From: http://www.cnblogs.com/magicsoar/p/3817518.html C++通过mysql的c api和通过mysql的Connector C++ 1.1.3操作 ...

  4. Font Awesome使用简介

      Font awesome是一种用字体来实现图标的CSS插件. 使用方法: 到http://fortawesome.github.io/Font-Awesome/ 下载代码包. 代码包解压到本地后, ...

  5. 通过WebRTC实现实时视频通信(二)

    通过WebRTC实现实时视频通信(一) 通过WebRTC实现实时视频通信(二) 通过WebRTC实现实时视频通信(三) 在上一篇文章中,我们讲解了WebRTC的概述.历史.安全性和开发者工具.接下来我 ...

  6. ios Mac 地址获取

    //mac address #include <sys/socket.h> // Per msqr #include <sys/sysctl.h> #include <n ...

  7. Android 之Toast

    Toast 是一个 View 视图,快速的为用户显示少量的信息. Toast 在应用程序上浮动显示信息给用户,它永远不会获得焦点,不影响用户的输入等操作,主要用于一些帮助 / 提示. Toast 最常 ...

  8. php之表单-1

    PHP 表单和用户输入 PHP 中的 $_GET 和 $_POST 变量用于检索表单中的信息,比如用户输入. PHP 表单处理 有一点很重要的事情值得注意,当处理 HTML 表单时,PHP 能把来自 ...

  9. CentOS 下安装MySQL 默认源为5.1版本

    CentOS——默认为安装5.1版本,如果需要安装5.5版本,需要使用remi源 yum install mysql-server –enablerepo=remi   Ubuntu——默认为安装5. ...

  10. break的使用方法

    private static void test() {  for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { Syst ...