socket句柄用尽 不能执行套接字上的操作.

路过路人乙 2013-03-23 02:46:02
程序用临时创建了几个clientsocket.然后定时向服务端发送数据

void __fastcall TfrmShow::tmrSendTimer(TObject *Sender)
{
tmrSend->Enabled = false;
for(int i = 0;i< n_Btnnum; i++)
{
AnsiString sStr = SocketClient[i]->Host;
SocketClient[i]->Port = m_Port;
if(SocketClient[i]->Active == false)
SocketClient[i]->Active = true;
SocketClient[i]->Socket->SendText("1"); //随便发送消息.服务端收到即可响应
}
tmrSend->Enabled = true;
}


在socket的ONERROR事件里如下写:
void __fastcall TfrmShow::OnSocketError(TObject *Sender, TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
in_addr inaddr;
inaddr = Socket->Addr.sin_addr;
AnsiString sAddr = inet_ntoa(inaddr);
//出现的均是通讯有问题的数据.
for(int i = 0;i< n_Btnnum; i++)
{
if(iledZsd[i]->Hint == sAddr)
{
Image[i]->Picture->LoadFromFile(ExtractFilePath(Application->ExeName) + "\\Image\\close.png");
//同时关闭此socket.防止用尽句柄
SocketClient[i]->Close();
SocketClient[i]->Active = false;
}
}

ErrorCode = 0;
}


为何已经关闭了..在运行程序大概几个小时后依然会出现系统缓冲空间不足.不能执行套接字上的操作.
...全文
2577 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
季雨林 2015-12-07
  • 打赏
  • 举报
回复
同求,我的程序只有3000并发连接,但是长时间运行后,却看到句柄数最多时候高达200万。一直没解决
cjs5210 2013-09-02
  • 打赏
  • 举报
回复
... 在服务器没开启或者死机情况下.就在客户端这边close不行吗.[/quote]
引用 13 楼 dataxdata 的回复:
什么时候结束要根据你的通信协议,通过接收服务器发回来的回复,可以判断是否已经不需要继续通信了,如果不需要继续通信,就可以关闭socket了。所以要在接收数据后判断,而不是发送的时候判断
我想楼主已经说得很明白了,服务端关掉的情况下,客户端连不上去是正常的。要解决的是在只有client长时间运行的这种情况下,怎么释放掉句柄来解决“系统缓冲空间不足.不能执行套接字上的操作”这个问题
路过路人乙 2013-03-24
  • 打赏
  • 举报
回复
刚以为可以了...呃..把代码加到之前的程序里面去发现句柄数还是在不停的上涨....到底哪里的问题呢..
路过路人乙 2013-03-24
  • 打赏
  • 举报
回复
引用 4 楼 zcchm 的回复:
打开windows任务管理器,看看你的程序句柄数是多少,如果socket句柄泄露导致无法创建新的socket,应该会看到句柄数很大。 “如果能正常通信的话.在serversocket那边的线程里在接受到信息后就关闭了该clientsocket了.. ” 一对tcp连接,关闭时4次握手,server和client都需要调用close的。
我现在是假设的服务器DOWN了或者没开机的情况直接运行客户端.. 我查了下句柄数..的确是不停变大的... 服务端那边在收到客户端的消息后是做了close处理了.. 在服务器没开启或者死机情况下.就在客户端这边close不行吗.
路过路人乙 2013-03-24
  • 打赏
  • 举报
回复
引用 3 楼 dataxdata 的回复:
需要同服务器同时保持几条连接? 如果连接是固定的话,就创建相应的几个socket保持不动,用于和fuwuwi通信,到程序结束时关闭; 如果不需要保持连接,可以每次动态创建或分配socket,通信结束后马上关闭
是需要和服务器实时保持链接..我这边测试的就是如果服务器没打开的情况下.仅使用client的情况.因为也不能排除服务器异常或者死机的情况... clientsocket数量是根据扫描局域网计算机后动态配置的文件里面读取后创建的.第一段代码就是写在time控件里不停向各个服务器发送数据..如果出错是会进入onerror这个里面的吧.然后在第二段代码就执行了close操作了.理论上是应该关闭了socket了..但是还是会出现缓存不够..不能执行套接字操作
路过路人乙 2013-03-24
  • 打赏
  • 举报
回复
引用 9 楼 dataxdata 的回复:
不是发送完就关,而是通信结束后关闭,就是要等到接收到服务器返回的数据后,不再跟服务器联系了,再关闭连接,下次需要通信的时候,再次重复“打开-发送-接收-关闭”这个过程
好了..搞定.... 其实我谷歌.百度了很久...这几天都被折磨着..跟你这个思路再琢磨了下..已经解决..贴上代码后结贴.. 将8L的第二段按钮里的代码做如下改动即可.
void __fastcall TForm1::btn2Click(TObject *Sender)
{
     if(ClientSocket->Active == false)
     {
        ClientSocket->Active = true;
         int nPd;
         nPd = ClientSocket->Socket->SendText(edt2->Text);
         if(nPd == 0)//没有发送成功.
         {
            ClientSocket->Close();
            ShowMessage("失败.");   
         }
     }
     else
     {
        int nPd;
         nPd = ClientSocket->Socket->SendText(edt2->Text);
         if(nPd == 0)
         {
            ClientSocket->Close();
            ShowMessage("失败.");   
         }   
     }
     
}
路过路人乙 2013-03-24
  • 打赏
  • 举报
回复
引用 9 楼 dataxdata 的回复:
不是发送完就关,而是通信结束后关闭,就是要等到接收到服务器返回的数据后,不再跟服务器联系了,再关闭连接,下次需要通信的时候,再次重复“打开-发送-接收-关闭”这个过程
请教.如何确认通信完毕呢..如果在服务器没开机的情况下.. 在clientsocket里也没有这样的事件判断.
dataxdata 2013-03-24
  • 打赏
  • 举报
回复
不是发送完就关,而是通信结束后关闭,就是要等到接收到服务器返回的数据后,不再跟服务器联系了,再关闭连接,下次需要通信的时候,再次重复“打开-发送-接收-关闭”这个过程
路过路人乙 2013-03-24
  • 打赏
  • 举报
回复
引用 7 楼 dataxdata 的回复:
timer事件中,要么不打开新的连接,直接用现有的连接,要么就打开新的连接后,在timer中关闭,不要等出错了再去关闭连接
你的意思是在我发送后就直接close吗? 我做了个简单的客户和服务端.服务端接受代码如下:
void __fastcall TServerThread::ClientExecute(void)
{//当一个客户连接的时候进入ClientExecute
              TWinSocketStream *pStream;
    char Buffer[2048];
    
    while (!Terminated && ClientSocket->Connected)
    {
        try
        {
            pStream = new TWinSocketStream(ClientSocket, 60000);
            try
            {
                memset(Buffer, 0, 2048); 
                
                if (pStream->WaitForData(60000))
                {
                    if (pStream->Read(Buffer, 10) == 0) 
                        ClientSocket->Close();           

                    Json::Value root;
                    Json::Value arrayObj;
                    for (int i = 0; i < 10; i++)
                    {
                        Json::Value item;
                        //机车种类
                        item["rq"] = "rq";
                        //机车种类
                        item["jczl"] = "jczl";
                        //机型
                        item["jx"] = "jx";
                        //机车号
                        item["jch"] = "jch";
                        //总走行
                        item["zzxgl"] = "zzxgl";
                        //沿线走行
                        item["yxgl"] = "yxgl";
                        //专调时间
                        item["zdsj"] = "zdsj";
                        arrayObj.append(item);
                    }
                    root["records"] = arrayObj;
                    ClientSocket->SendText(root.toStyledString().c_str());
                }
                else
                {
                    ClientSocket->Close(); 
                }
            }
            __finally
            {
                delete pStream;
            }
        }
        catch (Exception &E)
        {
            HandleException();
        }
    }
}
在客户端的发送按钮代码如下(已经连接上服务端)
void __fastcall TForm1::btn2Click(TObject *Sender)
{
     ClientSocket->Socket->SendText(edt2->Text);
     ClientSocket->Close();
}
这样会在服务端产生一个错误:error 64,指定的网络名不再可用. 如果我去掉发送的close就不会产生这个错误...应该是才发送就关闭的原因导致的..
dataxdata 2013-03-24
  • 打赏
  • 举报
回复
什么时候结束要根据你的通信协议,通过接收服务器发回来的回复,可以判断是否已经不需要继续通信了,如果不需要继续通信,就可以关闭socket了。所以要在接收数据后判断,而不是发送的时候判断
dataxdata 2013-03-24
  • 打赏
  • 举报
回复
timer事件中,要么不打开新的连接,直接用现有的连接,要么就打开新的连接后,在timer中关闭,不要等出错了再去关闭连接
zcchm 2013-03-23
  • 打赏
  • 举报
回复
打开windows任务管理器,看看你的程序句柄数是多少,如果socket句柄泄露导致无法创建新的socket,应该会看到句柄数很大。 “如果能正常通信的话.在serversocket那边的线程里在接受到信息后就关闭了该clientsocket了.. ” 一对tcp连接,关闭时4次握手,server和client都需要调用close的。
dataxdata 2013-03-23
  • 打赏
  • 举报
回复
需要同服务器同时保持几条连接? 如果连接是固定的话,就创建相应的几个socket保持不动,用于和fuwuwi通信,到程序结束时关闭; 如果不需要保持连接,可以每次动态创建或分配socket,通信结束后马上关闭
路过路人乙 2013-03-23
  • 打赏
  • 举报
回复
引用 1 楼 dataxdata 的回复:
最好用完就关闭
第二段代码就是将无法通信的clientsocket进行close了啊,但是似乎还是没有释放句柄....如果能正常通信的话.在serversocket那边的线程里在接受到信息后就关闭了该clientsocket了..
dataxdata 2013-03-23
  • 打赏
  • 举报
回复
最好用完就关闭

1,317

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder 网络及通讯开发
社区管理员
  • 网络及通讯开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧