Chinaunix

标题: socket的io操作为什么有的时候会阻塞? [打印本页]

作者: gloriajie    时间: 2004-09-10 18:16
标题: socket的io操作为什么有的时候会阻塞?
我在局域网里作实验,客户端和服务器端长时间通讯,客户端定时新建套接字,去连接server,接受数据,关闭套接字.
程序运行了三天都好好的,突然昨天就阻塞了不动了,我想知道什么原因会造成局域网里两台机器的阻塞呢?原因应该有很多吧,大家都说说意见好吗?

什么都没有改过
会不会应为内存不够用了造成的呢?


作者: 默难    时间: 2004-09-10 20:54
标题: socket的io操作为什么有的时候会阻塞?
连续运行三天?第三天就阻塞了?会不会是有内存泄漏呢?
作者: yeath    时间: 2004-09-10 21:06
标题: socket的io操作为什么有的时候会阻塞?
在程序阻塞的时候,看看你的TCP连接的状态,还有打印一些LOG,看看阻塞在哪一步?
作者: 默难    时间: 2004-09-10 21:26
标题: socket的io操作为什么有的时候会阻塞?
或者可以用嗅探工具(比如tcpdump之类的)来看看数据包~通过数据包来分析一下~
作者: gloriajie    时间: 2004-09-10 21:31
标题: socket的io操作为什么有的时候会阻塞?
tcp连接应该是没有问题,出问题的时候两台机器都在上网
日志是有的,每次connect,recv,send出错都有记载
发现是recv返回值<0.
很奇怪,我在写入日志后面,立刻就要求显出错误提示,可是日志写了,错误提示没有!!
server端关闭后客户端各按钮恢复正常了.

我得程序内存使用量确实在不停的变化,但是增长一段时间后有会下降,不停的循环,这个是内存泄漏的表现马?
作者: yeath    时间: 2004-09-10 23:52
标题: socket的io操作为什么有的时候会阻塞?
应该不是内存泄漏吧,你的程序是阻塞在那里,检查会不会是死循环,或者某个地方资源竞争造成死锁?
作者: CNL    时间: 2004-09-11 07:33
标题: socket的io操作为什么有的时候会阻塞?
检查server端程序,如果server是fork机制,
1、fork出来的子进程退出时是否没有调用exit
2、父进程fork之后是否忘了close了accept函数返回的子socket
作者: gloriajie    时间: 2004-09-11 09:54
标题: socket的io操作为什么有的时候会阻塞?
没有用fork机制.
对了还有一个问题,用bsd socket 要用select来防止阻塞是吗?
是不是要作两个线程,一个通讯,另一个用select来监测通讯线程里的socket是否可读什么的?
作者: babizhu    时间: 2004-09-12 17:29
标题: socket的io操作为什么有的时候会阻塞?
楼上,我决得你可能比较缺乏一些比较基础的网络编程知识,可能这样解决起来,会比较麻烦。
而且,你说的
程序运行了三天都好好的,突然昨天就阻塞了不动了
这样实在太含糊,是客户机不能连服务器?还是服务器不接受客户机的连接??我想没有人可以解决你的问题

还有阻塞这个词再socket编程里面是一个有意义的词,但是你说的这个阻塞似乎不是这个意思,建议换个词语形容,比如是不是程序不相应外部连接,或者拒绝外部连接什么的?

胡乱说了两句,不比当真,如果可能你可以贴出一部分源代码,我想可能会有帮助的
作者: gloriajie    时间: 2004-09-12 19:10
标题: socket的io操作为什么有的时候会阻塞?
确实是第一次接触网络编程,问题比较业余比较无厘头,还请各位多多包涵.

问题就在于我不知道哪边出了问题.
问题应该是出在server端send,客户端recv的时候.程序应该是停滞在这里.我将server端程序关掉后客户端提示recv返回值小于0.
我用阻塞一词是因为,我发现一般情况下,如果两端连接以后,都recv,那么两端的程序都会停滞在那里,我觉得这就是recv操作不能正常完成或者无法返回错误信息的表现,我觉得这就是阻塞的一种.而那天程序出问题时,表现和这个很像.

我也在查书继续学习,在提高之前,希望大家不要被我的初级问题气晕就好.
作者: eboymcy    时间: 2004-09-12 20:46
标题: socket的io操作为什么有的时候会阻塞?
把代码帖出无妨啊?
这样问题很快就被发现了。
作者: gloriajie    时间: 2004-09-13 01:22
标题: socket的io操作为什么有的时候会阻塞?
代码挺长的,有耐心的朋友看看吧.
server(要在openvms中运行)
void main()
{
   printsystime(systime); //将系统时间放在systime数组里并打印出来
   sock=socket(AF_INET, SOCK_STREAM,0);  //建立套接字
   if(sock<0)   
   {  perror("opening stream socket failed/n";
       exit(0);}
     setsockopt(sock,SOL_SOCKET,SO_SNDBUF,(const char*)& Sndbuf,sizeof(int));
     server.sin_family=AF_INET;   
     server.sin_port=htons(8800);           
     server.sin_addr.S_un.S_addr=htonl(INADDR_ANY);                              
     if(bind(sock,(struct sockaddr *)&server,sizeof(server))<0)
         {   
        perror("binding stream socket";
                closesocket(sock);  
         }
     printf("port #%d\n",ntohs(server.sin_port));
     length=sizeof(server);
     if(getsockname(sock,(struct sockaddr *)&server,&length)<0)
          perror("getting socket name";  
         int time=1;          
     while(true)
    {        
      err=listen(sock,1);  
      printf("listen...";   
      if(err!=0)
      {
        printf("listen failed";
            closesocket(sock);
           }
      len=sizeof(struct sockaddr);            
      msgsock=accept(sock,(struct sockaddr*)&tcpaddr,(int *)&len);
      if (msgsock==-1)
            perror("accept failed\n";
      else
          {                      
                 if(time==2)  //从第二次开始就发送数据
                 {
                    printsystime(buf);
                    GetChar(data0,buf,DATAnum);
                    rval=send(msgsock,buf, sizeof(buf),0);
                    if(rval<=0)perror("接收出错";                           
                    if(rval>;0)printf
                                      ("sendsuccessful );                                                     }
                 if(time==1)//第一次就接受数据
                 {
                         printf("begin to recv\n";
                         memset(buf,0,sizeof(buf));                 
                         rval=recv(msgsock,buf,10000,0);
                         if(rval>;0)
                         {分析接收到的数据;
                         time=2;} //下一次发送数据          
                         else printf("recv error\n";                                 
                   }
             closesocket(msgsock);               
          }          
        }
    closesocket(sock);
}
作者: gloriajie    时间: 2004-09-13 01:40
标题: socket的io操作为什么有的时候会阻塞?
客户端是在windows里用vc写的,主要是定时(每隔2秒钟)执行:
if(sendorrecv(bbuf,1,true))  //一个函数根据参数不同接收或发送数据
{getFloat(ddata2,bbuf,DATAnum);  //数据转换,buf->;data2
insertdata(bbuf,ddata2,DATAnum,pid);  //将data2内容写入数据库
}

sendorrecv函数主要如下:
   int sock;  //每次定义新的
   sock=socket(AF_INET, SOCK_STREAM,0);  
   server.sin_family=AF_INET;
   server.sin_port=htons(port);//atoi(port)
   server.sin_addr.S_un.S_addr=inet_addr(serverip);   
if(connect(sock,(const sockaddr*)&server,sizeof(server))<0)  
      closesocket(sock);
   else                     //connect成功
{
         int nRcvBuf=10000;
          setsockopt(sock,SOL_SOCKET,SO_RCVBUF,(const char*)&nRcvBuf,sizeof(int));
                           memset(buf,0,10000);   
                           rval=recv(sock,buf,10000,0);
}
if(rval<=0)
{... closesocket(sock);}
if(rval>;0)
                  {
                           closesocket(sock);
                           return(true);                      }
作者: 阿Benni    时间: 2004-09-13 09:23
标题: socket的io操作为什么有的时候会阻塞?
recv()<=0不一定是系统错误,需要判断一下错误号,如是WSAEWOULDBLOCK表示系统正常,不需要重新初始化!并且,你的server太简单了,没有超时判断,找找资料吧!
作者: HappyWin    时间: 2004-09-14 09:19
标题: socket的io操作为什么有的时候会阻塞?
是不是应该把while(true)循环中的listen拿到循环的外面来写呢?
作者: gloriajie    时间: 2004-09-14 09:30
标题: socket的io操作为什么有的时候会阻塞?
我原来试过放在外面,只能连接一次,我再试试
作者: 思一克    时间: 2004-09-14 09:31
标题: socket的io操作为什么有的时候会阻塞?
你的变量buf是如何定义的?
作者: gloriajie    时间: 2004-09-14 09:55
标题: socket的io操作为什么有的时候会阻塞?
char buf[10000];

哦,listen可以放在循环外面.只要客户端每次connect之前新建一个套接字就行了.
作者: hongbupt    时间: 2004-09-14 09:59
标题: socket的io操作为什么有的时候会阻塞?
你总是调用listen是不对的,循环中应该是accept
作者: gloriajie    时间: 2004-09-14 10:43
标题: socket的io操作为什么有的时候会阻塞?
这个用起来倒是好像没什么问题,起码三天之内,(呵呵,唉)
作者: gloriajie    时间: 2004-09-14 15:44
标题: socket的io操作为什么有的时候会阻塞?
服务器:
while(true)
{
  msgsock=accept(..);
  send(..);
  clsesocket(msgsock);
}

tv.tv_sec=10;
   tv.tv_usec=0;

客户端:
while(c<3)
{
    c++;
   sock=socket(AF_INET, SOCK_STREAM,0);           server.sin_family=..
   server.sin_port=..
   server.sin_addr.S_un.S_addr=..  
   
  connect(sock,(const sockaddr*)&server,sizeof(server))
   memset(buf,0,sizeof(buf));
   FD_ZERO(&fdread);
   FD_SET(sock,&fdread);
   ioctlsocket(sock,FIONBIO,&b);    //这句话效果加不加都一样
  if(ret=select(0,NULL,&fdread,NULL,&tv)<0)
   {
       printf("\nselect error";
       exit(0);
   }
   else    printf("%d",ret);
   if(FD_ISSET(sock,&fdread))
      recv(...);
closesocket(sock);
sock=NULL;
Sleep(50);
}
为什么ret总是0呢?而且select总是立刻返回,不论超时设为多少?怎么回事啊?




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2