免费注册 查看新帖 |

Chinaunix

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

模拟web服务器,出现 Connection reset by peer ,请教 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-03-18 17:19 |只看该作者 |倒序浏览
本帖最后由 sunceenjoy 于 2010-03-18 17:29 编辑

我模拟了一个最简单的web服务器,如下:
  1. #include "stdio.h"
  2. #include <sys/wait.h>
  3. #include <signal.h>
  4. #include <unistd.h>
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <netinet/in.h>
  8. #include <arpa/inet.h>
  9. #include <string.h>
  10. #include <errno.h>

  11. void sig(int i){
  12.         printf("receive signal\n");
  13. }

  14. int main(){
  15.         int child        = 0;
  16.         int nums        = 1;
  17.         
  18.         signal(SIGINT,sig);

  19.         struct sockaddr_in addr;
  20.         int alen        = sizeof(addr);
  21.         memset(&addr,sizeof(addr),0);
  22.         addr.sin_family        = AF_INET;
  23.         addr.sin_port        = htons(87);
  24.         addr.sin_addr.s_addr        = INADDR_ANY;
  25.         
  26.         int fd;
  27.     if ((fd = socket(AF_INET,SOCK_STREAM,0)) < 0){
  28.                 fprintf(stderr, "%s.%d: socket failed (%s)\n",__FILE__, __LINE__, strerror(errno));
  29.                 return -1;
  30.         }

  31.         {
  32.                 int reuse = 1;
  33.                 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse,sizeof(reuse));
  34.         }

  35.     if (bind(fd, (struct sockaddr*)&addr, alen) < 0) {
  36.         fprintf(stderr, "%s.%d: bind failed (%s)\n",__FILE__, __LINE__, strerror(errno));
  37.                 return -1;
  38.     }

  39.     if (listen(fd, 20) < 0) {
  40.         fprintf(stderr, "%s.%d: listen failed (%s)\n",__FILE__, __LINE__, strerror(errno));
  41.                 return -1;
  42.     }

  43.         while(1){
  44.                 int c;
  45.                 if((c=accept(fd,NULL,NULL))==-1){
  46.                         printf("get error:%d\n",errno);
  47.                 }else{
  48.                         char *str        = "HTTP/1.1 200 OK\n"
  49.                                "Content-Length: 10\n"
  50.                                 "Content-Type: text/html;charset=gbk\n\n"
  51.                                 "1234567890";
  52.                         size_t        len        = strlen(str);
  53.                         int pos        = 0;
  54.                         do{
  55.                                 int l        = send(c,str+pos,len-pos,0);
  56.                                 if(l<=0){
  57.                                         puts("error");
  58.                                         close(c);
  59.                                         continue;
  60.                                 }else{
  61.                                         pos        += l;
  62.                                 }
  63.                         }while(pos!=len);
  64.                         printf("close fd:%d\n",c);
  65.                         close(c);
  66.                 }

  67.         }
  68. }

复制代码
用浏览器可以访问,但为什么用apache的ab测试,老是出现:
[root@yt-newcvs jiguang]# /usr/local/apache/bin/ab -n 1 -c 1 http://192.168.2.151:87/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.2.151 (be patient)...apr_socket_recv: Connection reset by peer (104)

用ab试apache服务器正常,另外虽然上面出错,但服务器已经收到并发送完毕了(打印close fd:4)
网上查了,说是这个错误一般由于socket关闭了。也就是close. 我总不能不close吧。请问各位知情人士指教。

论坛徽章:
0
2 [报告]
发表于 2010-03-18 17:27 |只看该作者
客户先close,你再close!

论坛徽章:
0
3 [报告]
发表于 2010-03-18 17:30 |只看该作者
楼上的兄弟,apache,lighttpd都是你说那样做吗?

论坛徽章:
1
黑曼巴
日期:2020-02-27 22:54:26
4 [报告]
发表于 2010-03-18 17:35 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
5 [报告]
发表于 2010-03-18 17:42 |只看该作者
经过你们这么一说,感觉如下:
正常情况下服务器会等客户端先关闭然后再关闭,超时则主动关闭。

最近在看lighttpd的代码,等看那块再仔细看看。

顺便说下:lighttpd的watcher,worker模型 不会导致所谓的群惊现象。(测试这个才遇到这个问题)

论坛徽章:
0
6 [报告]
发表于 2010-03-18 17:53 |只看该作者
不对啊。好像客户端不是主动关闭的。如果是主动关闭,在71行之前加入:
                        char buf[1];
                        while(read(c,buf,1)>0);

应该不会一直阻塞啊。
而事实上,read永远阻塞(用ie测试的)

论坛徽章:
0
7 [报告]
发表于 2010-03-18 18:00 |只看该作者
本帖最后由 peidright 于 2010-03-18 18:08 编辑

我说的有问题,有可能ab 测试程序又用了fd,而那个fd确被你close();
想想,web服务器如果确认传输已经完毕,则应该主动关闭fd,但是ab 没有认为传输完毕。

论坛徽章:
1
黑曼巴
日期:2020-02-27 22:54:26
8 [报告]
发表于 2010-03-18 18:03 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
9 [报告]
发表于 2010-03-18 18:25 |只看该作者
各位,我之前是没有读浏览器发送过来的内容。
现在改成在发送之前把能读的都读了,就一切正常了。
(55行之前)加上:
  1.                         fd_set r;
  2.                         FD_ZERO(&r);
  3.                         FD_SET(c,&r);

  4.                         if(select(c+1,&r,NULL,NULL,NULL)<=0){
  5.                                 puts("select error\n");
  6.                                 continue;
  7.                         }

  8.                         int toread        = 0;
  9.                         if (ioctl(c, FIONREAD, &toread)) {
  10.                                 fprintf(stderr, "ioctl error\n");
  11.                                 return -1;
  12.                         }
  13.                         char *b        = (char*)malloc(toread+1);
  14.                         recv(c,b,toread,MSG_WAITALL);
  15.                         b[toread]        = 0;
  16.                         //puts(b);
  17.                         free(b);
复制代码
这是什么逻辑,这么回事?

论坛徽章:
0
10 [报告]
发表于 2010-03-18 18:30 |只看该作者
你把buf打出来就会发现,浏览器是"keep-alive"的,并没有马上关闭

你刷新一下或者关闭浏览器就知道了 ...
c/unix 发表于 2010-03-18 18:03



    你说的不错,如果刷新或关闭,那客户端肯定会主动close。但我说的是正常情况下啊,用户未关闭或刷新。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP