首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ Builder >

关于TClientSocket多线程运用时,需要加锁吗

2013-01-07 
关于TClientSocket多线程使用时,需要加锁吗?请在在主线程中有个TClientSocket,使用的是非阻塞模式工作。在C

关于TClientSocket多线程使用时,需要加锁吗?

请在在主线程中有个TClientSocket,使用的是非阻塞模式工作。在ClientSocketRead事件中,获得服务器发来的数据,

解析并保存在队列中。另外一个线程处理队列中的数据。处理完后,需要用Socket->SendBuf方法发送(写)数据到服务端。

请问各位,在这两个线程中主线程读(接收),另外子写(发送)。这样操作,需不需要加个 临界区之类的锁。把Socket操作

时,要分别锁起来? 谢谢。

官方文档里有句话:

Use a non-blocking socket when the socket needs to synchronize reading and writing with server sockets. 

不知道如何正确理解?

[解决办法]
非阻塞情况下这个必须要枷锁,因为你接受线程和发送线程是对同一个队列里的数据进行处理,存在资源竞争,需要枷锁进行保护,防止队列中的数据被改写
[解决办法]

引用:
请问 Socket->Lock()和Socket->Unlock()是不是工作在当ClientSocket工作在非阻塞模式的时候?

是不是对所有Socket操作的时候,如Socket->Sendbuf 和 Socket->ReceiveBuf 的时候要加上锁?


互斥锁。。。
[解决办法]
这个帖子时间这么长了。这个在阻塞模式是,不用加锁。只是要自己处理接收和发送的数据,由于是一对多,所以都是用多线程,就是每个客户端连接对应一个服务端的处理线程。具体
void __fastcall TServerFrm::ServerSocket1GetThread(TObject *Sender,
      TServerClientWinSocket *ClientSocket,
      TServerClientThread *&SocketThread)
{
    SocketThread=new MyServer(false,ClientSocket,600000);
}
这里产生客户端处理线程。
在线程体内大致这样处理
void __fastcall MyServer::Connected()
{
     ActiveNum++;
     RemoteHostIP=ClientSocket->RemoteAddress;
     RemoteHostProt=ClientSocket->RemotePort;
     Message="客户机:"+RemoteHostIP+":"+RemoteHostProt+" 已连接...";
     Synchronize((TThreadMethod)&AddMessage);
     ServerFrm->Label1->Caption="当前连接数:"+IntToStr(ActiveNum);
}
//---------------------------------------
void __fastcall MyServer::DisConnected()
{
     ActiveNum--;
     ServerFrm->Label1->Caption="当前连接数:"+IntToStr(ActiveNum);
     Message="客户机:"+RemoteHostIP+":"+RemoteHostProt+" 断开连接...";
     Synchronize((TThreadMethod)&AddMessage);
}
//---------------------------------------
void __fastcall MyServer::DataDisposal(void)   //所有数据处理
{
  char GetStr;
  String RevStr;
  char buf[1024+1];

 try{
      while(ClientSocket->Connected==true)
      {
           memset(buf,0,sizeof(buf));
           if(ReceiveStr(buf,1024)>0)
           {
                RevStr=String(buf);
                Message=RemoteHostIP+"::"+RevStr;
                Synchronize((TThreadMethod)&AddMessage);
               TransmitStr=RemoteHostIP+"::"+RevStr;
            }


          RevStr="";
          //以下进行数据转发
          if (TransmitStr!="")
          {
              bmsg=TransmitStr;
              SendStr("asdasd",6);//Synchronize((TThreadMethod)&BC);
              TransmitStr="";
          }
    }
 }
 catch(...)
 {
     return;
 }
}
//---------------------------------------
int __fastcall MyServer::ReceiveStr(char * _Buf,int length)  //接收数据
{
    if(length<=0) return 0;
    int aLen=0;
    int pos=0;
    char aBuf[255];

    int smalllen=0;

    if(length<=smalllen)   
        smalllen=length;
    else
        smalllen=SMALLLEN;

    TWinSocketStream *pStream;
    DWORD beginTick;

    beginTick=GetTickCount();
    while(!ClientSocket->Connected && GetTickCount()-beginTick<200);
    try{
        pStream = new TWinSocketStream(ClientSocket, 1000);
        try{
            if (pStream->WaitForData(TimeOutMSec)){
                while(pStream->WaitForData(100))
                 {
                    Application->ProcessMessages();
                    if((aLen=pStream->Read(aBuf,smalllen)) == 0)
                       {
                        ClientSocket->Close();
                        break;
                        }
                    else{
                        aBuf[aLen]=0;
                        memcpy(_Buf+pos,aBuf,aLen);
                        pos+=aLen;


                        if(pos>=length)
                            break;
                        if(length-pos<smalllen)    //promise get right byte no more no less
                            smalllen=length-pos;
                    }
                }
            }
            else ClientSocket->Close();
        }
        __finally{
            delete pStream;
        }
    }
    catch(Exception &E){
        Application->HandleException(this);
    }
    return pos;
}
//---------------------------------------
int __fastcall MyServer::SendStr(char * _Buf,int length)
{    //该函数未用到
    if(length<=0)
        return 0;
    int SendLen=0;
    TWinSocketStream *pStream;
    DWORD beginTick;

    beginTick=GetTickCount();
    while(!ClientSocket->Connected && GetTickCount()-beginTick<200);
    try{
        pStream = new TWinSocketStream(ClientSocket, 1000);
        try{
            SendLen=pStream->Write(_Buf,length);
        }
        catch(Exception &E){
            Application->HandleException(this);
        }
    }
    __finally{
        delete pStream;
    }
    return SendLen;
}
//---------------------------------------
void __fastcall MyServer::AddMessage() //将接收到的数据加入Memo1中
{
        ServerFrm->Memo1->Lines->Add(Message);
}
//---------------------------------------
void __fastcall MyServer::BC()   //数据转发
{
    ServerFrm->boardcast(bmsg);
    bmsg="";
}
//---------------------------------------

客户端的处理相似,代码太长发不完了,你留个邮箱,我把这个例子发给你,你看看。这个是一个网友写的例子,用来学习还是很好的。

热点排行