免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3689 | 回复: 19
打印 上一主题 下一主题

[函数] 关于socket的两个疑问 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-06-25 19:54 |只看该作者 |倒序浏览
下面是我的片断代码,是向某服务器发送数据请求

  1. #include <sys/socket.h>
  2. #include <netdb.h>
  3. #include <netinet/in.h>
  4. #include "zlib.h"
  5. #include "gzip.h"
  6. #include "globe.h"

  7. #define CRAWLER_ERR -1
  8. #define CRAWLER_SUCCESS        1

  9. static int channel_list_socket(void)
  10. {
  11.         int fd;        struct sockaddr_in channel_list_addr;
  12.        
  13.         struct hostent * host=NULL;                struct timeval tv_out;
  14.        
  15.         tv_out.tv_sec = 10;        tv_out.tv_usec = 0;
  16.        
  17.         //char list_ser[40] = "list.pplive.com";
  18.         //char list_ser[40] = "res.pplive.com";
  19.         char list_ser[40] = "vodchannel.pplive.com";
  20.        
  21.         if ((host = gethostbyname(list_ser)) == NULL)
  22.         {
  23.             fprintf(stderr, "gethostbyname() failed: %s\n", strerror(errno));
  24.            
  25.             return CRAWLER_ERR;
  26.         }
  27.        
  28.         if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  29.         {
  30.             fprintf(stderr, "socket() failed: %s\n", strerror(errno));
  31.            
  32.             return CRAWLER_ERR;
  33.     }
  34.    
  35.     memset(&channel_list_addr, 0, sizeof(channel_list_addr));
  36.    
  37.     channel_list_addr.sin_family = AF_INET;
  38.    
  39.     channel_list_addr.sin_port = htons(80);
  40.    
  41.     //channel_list_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  42.    
  43.     channel_list_addr.sin_addr = *((struct in_addr *)host->h_addr);
  44. /*   
  45.     if ((bind(fd, (struct sockaddr*)&srvaddr, sizeof(srvaddr))) < 0) {

  46.             fprintf(stderr, "bind() failed: %s\n", strerror(errno));
  47.            
  48.         close(fd);                return CRAWLER_ERR;
  49.     }
  50. */   
  51.     if(connect(fd, (struct sockaddr *)(&channel_list_addr), sizeof(struct sockaddr)) == -1)
  52.     {       
  53.             fprintf(stderr, "connect() failed: %s\n", strerror(errno));

  54.         close(fd);                return CRAWLER_ERR;
  55.     }
  56.    
  57.            if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (const char *)&tv_out, sizeof(tv_out)) == -1)
  58.         {
  59.                 fprintf(stderr, "setsockopt() for SO_SNDTIMEO failed: %s\n", strerror(errno));

  60.         close(fd);                return CRAWLER_ERR;
  61.         }
  62.         if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv_out, sizeof(tv_out)) == -1)
  63.         {
  64.                 fprintf(stderr, "setsockopt() for SO_RCVTIMEO failed: %s\n", strerror(errno));

  65.         close(fd);                return CRAWLER_ERR;
  66.         }
  67.        
  68.         return fd;
  69. }

  70. static int channel_list_extra(const char * list_buf)
  71. {       
  72.         char *gzip_start = NULL;        char *gzip_len = NULL;        int gziplen;       
  73.        
  74.         int decode_leng = 0;        char channel_list[1024*1024] = {0};       
  75.        
  76.         gzip_start = strstr(list_buf, "\r\n\r\n") + strlen("\r\n\r\n");
  77.        
  78.         gzip_len = strstr(list_buf, "Content-Length: ") + strlen("Content-Length: ");
  79.        
  80.         gziplen = atoi(gzip_len);
  81.        
  82.         gzip_decode((Byte*)channel_list, (uLong *)&decode_leng, (Byte*)gzip_start, (uLong)gziplen);
  83.        
  84.         fprintf(stderr, "*******\n%s\n*******\n", channel_list);
  85.        
  86.         return CRAWLER_SUCCESS;
  87. }

  88. int main(int argc, char * argv[])
  89. {
  90.         char require[1024] = {0};        int skt;        int len;       
  91.        
  92.         char list_buf_gzip[1024 * 512] = {0};        int how = 0;        int total = 0;       
  93.        
  94.         //snprintf(require, sizeof(require), "%s", "GET /zh-cn/xml/secure2.xml HTTP/1.1\r\nAccept: */*\r\nAccept-Encoding: gzip, deflate\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)\r\nHost: list.pplive.com\r\nConnection: Keep-Alive\r\nCache-Control: no-cache\r\n\r\n");
  95.         //snprintf(require, sizeof(require), "%s", "GET /passport/UI/Security/images/_css.css HTTP/1.1\r\nAccept: */*\r\nReferer: [url]http://passport.pplive.com/UI/Security/minilogin.aspx[/url]\r\nAccept-Language: zh-cn\r\nAccept-Encoding: gzip, deflate\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)\r\nHost: res.pplive.com\r\nConnection: Keep-Alive\r\n\r\n");
  96.         snprintf(require, sizeof(require), "%s", "GET /listall2.xml HTTP/1.1\r\nAccept: */*\r\nAccept-Encoding: gzip, deflate\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)\r\nHost: vodchannel.pplive.com\r\nConnection: Keep-Alive\r\nCache-Control: no-cache\r\n\r\n");
  97.                                        
  98.         if ((skt = channel_list_socket()) == -1){        exit(EXIT_FAILURE);                }
  99.                
  100.         len = strlen(require);
  101.        
  102.         if ((send(skt, require, len, 0)) != len)
  103.         {
  104.                 fprintf(stderr, "send require error: %s\n", strerror(errno));
  105.                
  106.                 exit(EXIT_FAILURE);
  107.         }
  108.        
  109.         do
  110.         {       
  111.             if ((how = recv(skt, &list_buf_gzip[total], 1024*512, 0)) == -1)
  112.             {
  113.                     fprintf(stderr, "recv channel list error: %s\n", strerror(errno));
  114.                    
  115.                     exit(EXIT_FAILURE);
  116.             }
  117.            
  118.             total += how;
  119.            
  120.         }while(how > 0);
  121.        
  122.         /* another way to know total gzip num
  123.         char *compr = NULL;        int comlen;
  124.        
  125.         compr = strstr(list_buf_gzip, "\r\n\r\n") + strlen("\r\n\r\n");
  126.        
  127.         comlen = total + list_buf_gzip - compr;
  128.        
  129.         fprintf(stderr, "compress len is %d\n", comlen);
  130.         */
  131.        
  132.         fprintf(stderr, "*******(%d---%d)\n%s\n*******\n", strlen(list_buf_gzip), total, list_buf_gzip);
  133.        
  134.         close(skt);
  135.        
  136.         shutdown(skt, 2);
  137.        
  138.         channel_list_extra(list_buf_gzip);

  139.         return EXIT_SUCCESS;
  140. }
复制代码


1.实际运行中发现程序阻塞在recv;如果设置超时,结果就超时退出;反正socket接受不到任何数据,但是我用抓包程序,发现服务器已经返回数据,这是为什么?
2.我用抓包程序,发现没有四次握手的连接断开,为什么?看书说close不一定会有四次握手,后来加了shutdown还是不行
3.请知道的说明一下,谢谢

[ 本帖最后由 kukule75 于 2008-6-25 21:17 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2008-06-25 20:03 |只看该作者
大牛呢

论坛徽章:
0
3 [报告]
发表于 2008-06-25 20:14 |只看该作者
你服务器在发送完数据之后调用了close()没有呢?

论坛徽章:
0
4 [报告]
发表于 2008-06-25 20:16 |只看该作者
原帖由 scutan 于 2008-6-25 20:14 发表
你服务器在发送完数据之后调用了close()没有呢?


服务器程序不是我写的,我是模仿某软件的行为,冒充客户端

论坛徽章:
0
5 [报告]
发表于 2008-06-25 20:19 |只看该作者

回复 #4 kukule75 的帖子

嗯, 我想你的程序阻塞在recv那个地方, 一是服务器没有发送数据, 二是服务器没有调用close()断开连接, 所以你就一直阻塞在那个地方了. 我建议你再运行一下真实的客户端, 抓包看看在那个地方是怎样处理的.
难道你是在写P2P客户端?

论坛徽章:
0
6 [报告]
发表于 2008-06-25 20:22 |只看该作者
原帖由 scutan 于 2008-6-25 20:19 发表
嗯, 我想你的程序阻塞在recv那个地方, 一是服务器没有发送数据, 二是服务器没有调用close()断开连接, 所以你就一直阻塞在那个地方了. 我建议你再运行一下真实的客户端, 抓包看看在那个地方是怎样处理的.
难道 ...


不是,服务器有数据返回的,我用libnids抓到了;可是socket怎么没数据呢

论坛徽章:
0
7 [报告]
发表于 2008-06-25 20:27 |只看该作者

回复 #6 kukule75 的帖子

有数据返回而socket不返回的话就可能是其它哪儿的问题了. 系统不会这么脆弱的.
还有, 你看的哪本书上说close()不一定有四次握手?

论坛徽章:
0
8 [报告]
发表于 2008-06-25 20:30 |只看该作者
原帖由 scutan 于 2008-6-25 20:27 发表
有数据返回而socket不返回的话就可能是其它哪儿的问题了. 系统不会这么脆弱的.
还有, 你看的哪本书上说close()不一定有四次握手?


unix网络编程;close只是将某计数器减1,如果计数器大于零,close并不引发四次握手

论坛徽章:
0
9 [报告]
发表于 2008-06-25 20:32 |只看该作者

回复 #8 kukule75 的帖子

哦, 呵呵, 是我想简单了. 没想到引用计数这种情况.
不过我觉得你再检查一下逻辑上面的问题看.

论坛徽章:
0
10 [报告]
发表于 2008-06-25 20:34 |只看该作者
想破脑袋了,哪位大牛知道怎么回事啊
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP