您的位置:首页 > 理论基础 > 计算机网络

socket 请求接收完整的一个http响应(设置recv 接收超时选项SO_RCVTIMEO)

2013-11-08 14:35 901 查看
在前面的系列网络编程文章中,我们都是使用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?程序中

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,在阻塞模式下不等到指定数目的数据是不会返回的,除非超时时间到。但在这里我们并不知道对方会发来具体多少数据,所以不能使用这种方法来读取数据,否则可能出现一直阻塞的情况。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐