Chinaunix首页 | 论坛 | 博客
  • 博客访问: 517180
  • 博文数量: 91
  • 博客积分: 9223
  • 博客等级: 中将
  • 技术积分: 1777
  • 用 户 组: 普通用户
  • 注册时间: 2007-04-02 17:37
个人简介

!!!!!!!!!!!!

文章分类

全部博文(91)

文章存档

2013年(3)

2012年(4)

2011年(37)

2010年(36)

2009年(9)

2008年(2)

分类: LINUX

2010-12-16 20:08:17

关闭socket前没有将缓冲区的数据发送完,而是直接关了

 

 转。

 

问题:见下面的例子,现在发现每次连接发送数据后,都要加taskDelay(10);后,客户端才能收到数据。否则就直接关闭了socket,没有发数据。
int HttpSvr(void)
{
int nServerFd, nConnectionFd,i;
struct sockaddr_in servAddr;
int nMsgNum;
struct linger optVal;
int addrLen = 0;
/*
初始web固态页面*/
if(ERROR == InitWebFile())
{
    myLogMsg("Info:ERROR  == InitWebFile\n",0,0,0,0,0,0);
     return ;
}
/*
清空
ArrHttpSessions*/
       clearHttpSessions();
       optVal.l_onoff = 1;
       optVal.l_linger = 0;
nServerFd = socket(AF_INET, SOCK_STREAM, 0);
if(ERROR == nServerFd)
{
     myLogMsg("Info:ERROR  == nServerFd\n",0,0,0,0,0,0);
     return ;
}
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(HTTP_SERVER_PORT);
addrLen = sizeof(struct sockaddr_in);
if(ERROR  == bind(nServerFd, (struct sockaddr*)&servAddr, sizeof(servAddr)))
{
     myLogMsg("Info:ERROR  == bind\n",0,0,0,0,0,0);
     return ;
}
if(ERROR == listen(nServerFd, 10))
{
     myLogMsg("Info:ERROR  == listen\n",0,0,0,0,0,0);
     return ;
}
while(1)
{
  nConnectionFd = accept(nServerFd, (struct sockaddr*)&ClientAddr, &addrLen);
  if(ERROR  == nConnectionFd)
  {
     continue ;
  }
        if (
setsockopt (nConnectionFd, SOL_SOCKET, SO_LINGER, (char*)&optVal,
      sizeof (optVal)) == ERROR)
  
  {
         shutdown(nConnectionFd,2);
   close (nConnectionFd);
   continue ;
  }
        hangdleConnection(nConnectionFd);
        shutdown(nConnectionFd,2);
        taskDelay(10);
        close(nConnectionFd);
}

return 0;
}

 

答复:问题的根源在于optVal.l_linger不能设置为0,如果设置为0,表示立即关闭socket,不管缓冲区是否还有数据要发送。另外socket的属性SO_LINGER是必须的。此选项指定函数close对面向连接的协议如何操作(如TCP)。缺省close操作是立即返回,如果有数据残留在socket缓冲区中则系统将试着将这些数据发送给对方。
SO_LINGER
选项用来改变此缺省设置。使用如下结构:
struct linger {
     int l_onoff; /* 0 = off, nozero = on */
     int l_linger; /* linger time */
};
有下列三种情况:
l_onoff
0,则该选项关闭,l_linger的值被忽略,等于缺省情况,close立即返回;
l_onoff
为非0l_linger0,则套接口关闭TCP连接时,TCP将丢弃保留在套接口发送缓冲区中的任何数据并发送一个RST给对方,而不是通常的四分组终止序列,这避免了TIME_WAIT状态;
l_onoff
为非0l_linger为非0当套接口关闭时内核将拖延一段时间(由l_linger决定)。如果套接口缓冲区中仍残留数据,进程将处于睡眠状态,直 到(a)所有数据发送完且被对方确认,之后进行正常的终止序列(描述字访问计数为0)或(b)延迟时间到。此种情况下,应用程序检查close的返回值是非常重要的,如果在数据发送完并被确认前时间到,close将返回EWOULDBLOCK错误且套接口发送缓冲区中的任何数据都丢失。close的成功返回仅告诉我们发送的数据(和FIN)已由对方TCP确认,它并不能告诉我们对方应用进程是否已读了数据。如果套接口设为非阻塞的,它将不等待close完成

阅读(6139) | 评论(3) | 转发(1) |
给主人留下些什么吧!~~

yjz14092762016-06-17 18:44:48

终于找到答案了,今天面试的时候正好问道这个问题,没答上来

chinaunix网友2011-01-03 18:09:14

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com

chinaunix网友2011-01-03 18:08:58

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com