免费注册 查看新帖 |

Chinaunix

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

【求助】socket编程,TCP连接 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-03-05 13:48 |只看该作者 |倒序浏览
大家好,我现在遇到了一个问题,请大家帮忙看下。

我使用socket编程,TCP连接,做服务器。在客户端连接上之后,只要客户端退出,服务器端的软件也随之终止,这个问题该如何解决?

代码如下:


while (1)
{
  if ((netlistenfd = InitSndSocket(&serverinfo,port)) > 0) //函数在下方
  {
   break;
  }
}
SetBlock_Srv(netlistenfd,1);//函数在下方
if (bind(netlistenfd,(struct sockaddr*)&serverinfo,sizeof(serverinfo))<0)
{
   printf("bind to port %d failure!\n",port);
   exit(-1);
   }
if (listen(netlistenfd,LISTENQUEUE) < 0)
{
   printf("call listen failure!\n");
   exit(-1);
}
   
DBG("Entering netlisten main loop.\n");
while(1)
{
  clientinfolength = sizeof(clientinfo);
  printf("listening......................\n");
  netlistenclifd = accept(netlistenfd,(struct sockaddr*)&clientinfo,&clientinfolength);
  printf("accept link : socket id:%d\n",netlistenclifd);
  if (netlistenclifd < 0)
  {
       printf("error comes when call accept!\n");
  }
  else
  {
    if (pthread_create(&netsndThread, &pattr, netsndThrFxn, &netsndEnv)) //创建一个新线程处理,线程函数在本楼底部和第9楼都给了
   {
    ERR("Failed to create video thread\n");
    cleanup(EXIT_FAILURE);
   }
  }
}



int InitSndSocket(struct sockaddr_in *serverinfo,  int port)
{
int socketid = 0;
struct sockaddr_in  serverfd;
// UDP Sockets
if((socketid=socket(AF_INET,SOCK_STREAM,0))<0)      //SOCK_DGRAM
{
  fprintf(stderr,"InitSndSocket() create socket: %d FAIL\n",socketid);
  return(-1);
}
/// Initialize Socket Informations
memset((char *)&serverfd,0,sizeof(serverfd));
serverfd.sin_family=AF_INET;
serverfd.sin_addr.s_addr = htons(INADDR_ANY);//tcp server
serverfd.sin_port=htons(port);
*serverinfo = serverfd;
return(socketid);
}


int    SetBlock_Srv(int fd,int flag)
{
int    flags;
if((flags=fcntl(fd,F_GETFL,0))==-1)
{
  perror("fcntl");
  return -1;
}
if(flag==0)
{
  // Non Block Socket
  fcntl(fd,F_SETFL,flags|O_NDELAY);
}
else if(flag==1)
{
  // Block Socket
  fcntl(fd,F_SETFL,flags&~O_NDELAY);
}
return 0;
}

void        *netsndThrFxn(void *arg)
{
        NetsndBufferElement wFlush        = { NETSND_FLUSH };
        NetsndEnv          *envp          = (NetsndEnv *) arg;
        void               *status        = THREAD_SUCCESS;
        NetsndBufferElement we;
        int i = 0,k = 0;
        int netsndclifd = envp->socketid;
        DBG("Message Send Thread Start\n");

        DBG("Entering netsnd main loop.\n");

        /// Message Send Loop
        while (1)
        {

                if (FifoUtil_get(&envp->inFifo, &we) == FIFOUTIL_FAILURE) //获取数据,用于发送
                {        
                        ERR("fail:FifoUtil_get\n");
                        breakLoop(THREAD_FAILURE);
                }

                if (we.id == NETSND_FLUSH)
                {
                        ERR("fail:NETSND_FLUSH\n");
                        breakLoop(THREAD_SUCCESS);
                }
               
                if (we.id != NETSND_PRIME && we.frameSize)
                {
                        DBG("frameSize:%d\n",we.frameSize);
                        k = we.frameSize / 1400;
                        if(k)
                        {
                                for(i = 0;i < k;i++)
                                {
                                        if ( send(netsndclifd, (char *)(we.encodedBuffer + i * 1400), 1400, 0) < 0 )
                                        {
                                                /* send error */
                                                ERR("Error send the encoded data to network\n");
                                        }
                                }
                        }
                        if ( send(netsndclifd, (char *)(we.encodedBuffer + k * 1400), we.frameSize - k * 1400, 0) < 0 )
                        {
                                /* send error */
                                ERR("Error send the encoded data to network\n");
                        }
                }
                else
                {
                        we.id = NETSND_NORMAL;
                }

                if (FifoUtil_put(&envp->outFifo, &we) == FIFOUTIL_FAILURE) //通知其他线程,数据已经读取
                {
                        ERR("Failed to put buffer in output fifo\n");
                        breakLoop(THREAD_FAILURE);
                }

        }
        
        return status;
}

[ 本帖最后由 xinuaile2003 于 2009-3-6 08:52 编辑 ]

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
2 [报告]
发表于 2009-03-05 13:53 |只看该作者

回复 #1 xinuaile2003 的帖子

这是win下的东东,函数接口看起来怪怪的

论坛徽章:
0
3 [报告]
发表于 2009-03-05 13:58 |只看该作者
原帖由 dreamice 于 2009-3-5 13:53 发表
这是win下的东东,函数接口看起来怪怪的


linux下的,使用c编写的

论坛徽章:
0
4 [报告]
发表于 2009-03-05 14:35 |只看该作者
对客户端退出事件做处理

论坛徽章:
0
5 [报告]
发表于 2009-03-05 17:17 |只看该作者
客户断开连接会有一个close socket
而你这边会有一个信号,当收到这个信号你就可以做出处理的

论坛徽章:
0
6 [报告]
发表于 2009-03-05 19:59 |只看该作者
我怀疑是你创建的服务器纯种在客户端关闭时处理上有问题吧,刚一个线程非法退出(产生Segmentation fault)时就会导致整个进程终止。你给的代码不全也看不出啥来。

论坛徽章:
0
7 [报告]
发表于 2009-03-06 08:18 |只看该作者
原帖由 墨小白 于 2009-3-5 17:17 发表
客户断开连接会有一个close socket
而你这边会有一个信号,当收到这个信号你就可以做出处理的



那怎么获取这个close socket的信号呢?

论坛徽章:
0
8 [报告]
发表于 2009-03-06 08:19 |只看该作者
原帖由 Cyberman.Wu 于 2009-3-5 19:59 发表
我怀疑是你创建的服务器纯种在客户端关闭时处理上有问题吧,刚一个线程非法退出(产生Segmentation fault)时就会导致整个进程终止。你给的代码不全也看不出啥来。



我也感觉是线程非法退出导致的,可是找不到头绪。

论坛徽章:
0
9 [报告]
发表于 2009-03-06 08:50 |只看该作者
我把创建的线程代码也放上去吧


void        *netsndThrFxn(void *arg)
{
        NetsndBufferElement wFlush        = { NETSND_FLUSH };
        NetsndEnv          *envp          = (NetsndEnv *) arg;
        void               *status        = THREAD_SUCCESS;
        NetsndBufferElement we;
        int i = 0,k = 0;
        int netsndclifd = envp->socketid;
        DBG("Message Send Thread Start\n");

        DBG("Entering netsnd main loop.\n");

        /// Message Send Loop
        while (1)
        {

                if (FifoUtil_get(&envp->inFifo, &we) == FIFOUTIL_FAILURE) //获取数据,用于发送
                {        
                        ERR("fail:FifoUtil_get\n");
                        breakLoop(THREAD_FAILURE);
                }

                if (we.id == NETSND_FLUSH)
                {
                        ERR("fail:NETSND_FLUSH\n");
                        breakLoop(THREAD_SUCCESS);
                }
               
                if (we.id != NETSND_PRIME && we.frameSize)
                {
                        DBG("frameSize:%d\n",we.frameSize);
                        k = we.frameSize / 1400;
                        if(k)
                        {
                                for(i = 0;i < k;i++)
                                {
                                        if ( send(netsndclifd, (char *)(we.encodedBuffer + i * 1400), 1400, 0) < 0 )
                                        {
                                                /* send error */
                                                ERR("Error send the encoded data to network\n");
                                        }
                                }
                        }
                        if ( send(netsndclifd, (char *)(we.encodedBuffer + k * 1400), we.frameSize - k * 1400, 0) < 0 )
                        {
                                /* send error */
                                ERR("Error send the encoded data to network\n");
                        }
                }
                else
                {
                        we.id = NETSND_NORMAL;
                }

                if (FifoUtil_put(&envp->outFifo, &we) == FIFOUTIL_FAILURE) //通知其他线程,数据已经读取
                {
                        ERR("Failed to put buffer in output fifo\n");
                        breakLoop(THREAD_FAILURE);
                }

        }
       
        return status;
}

论坛徽章:
0
10 [报告]
发表于 2009-03-06 09:57 |只看该作者

回复 #7 xinuaile2003 的帖子

我说的是正常退出情况下  recv函数会返回0

对于非法退出的话 可以设置一个心跳机制

client每间隔M秒发一个心跳包给server
若连续N秒server端没有收到client的心跳包,则认为client已经去见马克思了

[ 本帖最后由 墨小白 于 2009-3-6 10:09 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP