免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: kuaizaifeng
打印 上一主题 下一主题

问一个socket里面shutdown和close的问题 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2007-07-25 17:56 |只看该作者

回复 #11 kuaizaifeng 的帖子

shutdown当然会激发FIN等关闭序列但是之后那个描述字仍然在那个地方放着.

论坛徽章:
0
12 [报告]
发表于 2007-07-25 17:57 |只看该作者
原帖由 scutan 于 2007-7-25 17:52 发表
描述字有一个引用计数. close把描述字的引用计数减1, 仅在该计数变为0时才关闭套接口. 而shutdown可以不管引用计数就激发TCP的正常连接终止序列了.


可以确定,引用计数是1,所以close的时候先减一,然后看看是0,就关闭了
这是正确的,也符合我的情况
但是我直接用shutdown的时候,为啥查看/proc/pid/fd下面的文件,发现在不断的涨,最终导致了fd溢出
fd溢出後,server就无法提供服务了吧

论坛徽章:
0
13 [报告]
发表于 2007-07-25 17:59 |只看该作者
原帖由 scutan 于 2007-7-25 17:56 发表
shutdown当然会激发FIN等关闭序列但是之后那个描述字仍然在那个地方放着.


这样啊
那么怎样才能把那个描述字干掉?
调用close?
我曾经试过在shutdown後调用close,但是返回EBADF fd isn't a valid open file descriptor.
而且,/proc/pid/fd下的描述字也没有减少

论坛徽章:
0
14 [报告]
发表于 2007-07-25 18:23 |只看该作者
应该是代码其它什么地方出了问题吧, 有shutdown()后面调用close()这种用法.

论坛徽章:
0
15 [报告]
发表于 2007-07-25 18:25 |只看该作者
原帖由 scutan 于 2007-7-25 18:23 发表
应该是代码其它什么地方出了问题吧, 有shutdown()后面调用close()这种用法.


恩,貌似在.NET里面看到过
不过这是linux下的程序
shutdown後在close就报错了

论坛徽章:
0
16 [报告]
发表于 2007-07-25 19:03 |只看该作者
原帖由 kuaizaifeng 于 2007-7-25 18:25 发表


恩,貌似在.NET里面看到过
不过这是linux下的程序
shutdown後在close就报错了


在Linux下也是可以的,你试试下面的这个程序:
在shutdown后面再调用close(), 仍然返回成功.
server 端:

  1. #include<stdio.h>
  2. #include<sys/socket.h>
  3. #include<netinet/in.h>
  4. #include<arpa/inet.h>
  5. #include<netdb.h>
  6. #include<stdlib.h>
  7. #include<string.h>

  8. int main()
  9. {
  10.         struct sockaddr_in sin;
  11.         struct sockaddr_in pin;
  12.         int socketfd;
  13.         int tmpsock;
  14.         int size;
  15.         char buf[10000];
  16.         int len;

  17.         struct sockaddr_in local;
  18.         char client[20] = {0};

  19.         if ((socketfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  20.         {
  21.                 perror("socket error\n");
  22.                 exit(1);
  23.         }

  24.         memset(buf, 0, sizeof(buf));
  25.         memset(&sin, 0, sizeof(sin));
  26.         sin.sin_family = AF_INET;
  27.         sin.sin_addr.s_addr = htonl(INADDR_ANY);
  28.         sin.sin_port = htons(12345);


  29.         if (bind(socketfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
  30.         {
  31.                 perror("bind error\n");
  32.                 exit(1);
  33.         }

  34.         if (listen(socketfd, 20) < 0)
  35.         {
  36.                 perror("listen error\n");
  37.                 exit(1);
  38.         }

  39.         printf("accept...\n");

  40.         if ((tmpsock = accept(socketfd, (struct sockaddr*)&pin, &size)) < 0)
  41.         {
  42.                 perror("accept error\n");
  43.                 exit(1);
  44.         }

  45.         if((len = read(tmpsock, buf, 10000))  > 0)
  46.         {
  47.                 printf("buflen = %d\n", strlen(buf));
  48.                 printf("len = %d\n", len);
  49.         }

  50.         printf("final len = %d\n", len);

  51.         printf("from %s, port %d\n", inet_ntop(AF_INET, &pin.sin_addr, client, sizeof(client)), ntohs(pin.sin_port));

  52.         if (send(tmpsock, "helloworld", 11, 0) < 0)
  53.         {
  54.                 perror("send\n");
  55.                 exit(1);
  56.         }
  57.         printf("send ok\n");
  58.         if (shutdown(tmpsock, SHUT_RDWR) < 0)
  59.         {
  60.                 perror("shutdown\n");
  61.                 exit(1);
  62.         }
  63.         else
  64.                 printf("shutdown ok\n");

  65.         if (shutdown(tmpsock, SHUT_RDWR) < 0)
  66.         {
  67.                 perror("shutdown 2 error\n");
  68.         }
  69.         else
  70.                 printf("shutdown 2 ok\n");
  71.         if (close(tmpsock) < 0)
  72.         {
  73.                 perror("close error\n");
  74.                 exit(1);
  75.         }
  76.         else
  77.                 printf("close ok\n");
  78.         return 0;

  79. }

复制代码


client端:

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<sys/socket.h>
  4. #include<netinet/in.h>
  5. #include<netdb.h>
  6. #include<arpa/inet.h>
  7. #include<string.h>
  8. #include<sys/types.h>
  9. #include<fcntl.h>
  10. #include<unistd.h>

  11. int main(int argc, char *argv[])
  12. {
  13.         char buf[10000];
  14.         int socketfd;
  15.         struct sockaddr_in pin;
  16.         struct hostent *server;
  17.         int len;
  18.         int fd;
  19.         int readlen;

  20.         if ((server = gethostbyname(argv[1])) == 0)
  21.         {
  22.                 perror("gethostbyname error\n");
  23.                 exit(1);
  24.         }

  25.         memset(&pin, 0, sizeof(pin));
  26.         pin.sin_family = AF_INET;
  27.         pin.sin_addr.s_addr = ((struct in_addr*)(server->h_addr))->s_addr;
  28.         pin.sin_port = htons(12345);
  29.         memset(buf, 0, sizeof(buf));

  30.         printf("pin.s_addr=%d\n", pin.sin_addr.s_addr);
  31.         if ((socketfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  32.         {
  33.                 perror("socket error\n");
  34.                 exit(1);
  35.         }

  36.         if (connect(socketfd, (struct sockaddr*)&pin, sizeof(pin)) < 0)
  37.         {
  38.                 perror("connect error\n");
  39.                 exit(1);
  40.         }

  41.         printf("connected...\n");

  42.         printf("send...\n");

  43.         if ((len = write(socketfd, "helloworld", 11)) == -1)
  44.         {
  45.                 perror("send error\n");
  46.                 exit(1);
  47.         }

  48.         printf("recv\n");

  49.         if (read(socketfd, buf, sizeof(buf)) < 0)
  50.         {
  51.                 perror("read\n");
  52.                 exit(1);
  53.         }
  54.         printf("buf=%s\n", buf);
  55.         sleep(2);
  56.         close(socketfd);
  57.         return 0;
  58. }

复制代码

论坛徽章:
0
17 [报告]
发表于 2007-07-25 19:41 |只看该作者
你如果服务器端关掉连接 那么它将进入TIME_WAIT状态 至少要保存此描述字2MSL时间, 以防止发送最后的FIN_ACK

我个人看法 不一定对

论坛徽章:
0
18 [报告]
发表于 2007-07-25 20:57 |只看该作者
原帖由 scutan 于 2007-7-25 19:03 发表


在Linux下也是可以的,你试试下面的这个程序:
在shutdown后面再调用close(), 仍然返回成功.
server 端:

#include
#include
#include
#include
#include
#include
#include

int main()
{
   ...

缘何在我的机器上shutdown後再close就失败了?
明天我去公司的机器上再试试看

论坛徽章:
0
19 [报告]
发表于 2007-07-25 22:17 |只看该作者
在弱弱的问一下
shutdown 和 close对UDP来说,也会激发4组关闭序列吗 ?
我翻了翻unix网络编程,发现在讲关闭序列的时候是针对TCP的
对UDP也适合吗?

论坛徽章:
0
20 [报告]
发表于 2007-07-25 22:45 |只看该作者
原帖由 kuaizaifeng 于 2007-7-25 22:17 发表
在弱弱的问一下
shutdown 和 close对UDP来说,也会激发4组关闭序列吗 ?
我翻了翻unix网络编程,发现在讲关闭序列的时候是针对TCP的
对UDP也适合吗?


UDP协议开始时没有三次握手过程啊. 后面结束时也不需要这个吧, 而且它都不能够确认包是否真正到达!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP