[ENet-discuss] ENet-Client or Server issue?

Thorbjørn Lindeijer bjorn at lindeijer.nl
Mon May 27 01:10:15 PDT 2013


Hey Andy,

I can see two problems with your code:

* In your sending loop, you got three 'return' statements where you
may exit the function without unlocking your global thread lock. The
cases may be rare, but if that happens it will lead to problems. A
common solution for this problem is to use a thread locker object on
the stack that will unlock on destruction and thereby automatically
unlock whenever your function returns.

* In your receiving code, you lock the global thread lock only in some
specific cases. However, since enet is not thread-safe you need to
wrap the whole while loop with a lock (including enet_host_service).
In general it seems you're only protecting access to your mRecvBuffer
and mSendBuffer, but you need to realize enet doesn't do any locking
on its own data types either.

Some additional hints:

* Consider having just one thread that does both sending and
receiving. What are you trying to achieve by separating this? If you
would do that you wouldn't need to do locking for enet and protecting
your send/receive buffers would be enough.
* Note that you generally do not need to use a thread for enet at all.
You can pass a 0-timeout to enet_host_service and call it regularly
from your main thread instead. That would avoid the whole locking
stuff.

Regards,
Bjørn

On Mon, May 27, 2013 at 4:53 AM, Andy Zheng <zxz3121 at gmail.com> wrote:
> hi,sorry to reply such late!
> I put send and receive in two different threads
> here is the part of sending:
> while (!mSendBuffer.isEmpty() && mConnect)
> {
> if(safety)
> GlobalThreadLock.Lock();
> PacketBuffer* pack = mSendBuffer.getFront();
>
> const char* pszText = (const char*)pack->buf.base();
> //ELOG("buf :%s",pszText);
> if(NULL == pszText)
> {
> ELOG("send buf is null");
> continue;
> }
> ENetPacket
> *packet=enet_packet_create(pszText,strlen(pszText)+1,ENET_PACKET_FLAG_RELIABLE);
>
> if (NULL == mPeer)
> {
> ELOG("mPeer is NULL");
> return;
> }
> int channle = rand()%mChannelLimit;
> if(pack->flags)
> enet_host_broadcast(mHost ,channle ,packet);
> else
> {
> int reval = enet_peer_send(mPeer,channle,packet);
>
> if (reval != 0)
> {
> ELOG("send msg failed");
> return;
> }
> }
> pack->buf.clear();
> delete pack;
> mSendBuffer.dequeue();
> if(safety)
> GlobalThreadLock.Unlock();
> }
>
> and here is the part of receiving:
>
> while(enet_host_service(mHost,&mEvent,mRecvDelay)>=0)
> {
> if(Thread_Pause)
> {
> ELOG("Thread wait");
> GlobalThreadLock.wait();
> }
> if(mEvent.type==ENET_EVENT_TYPE_CONNECT)
> {
> if(mType == SERVER)
> {
> if(safety)
> GlobalThreadLock.Lock();
> static unsigned int num=0;
> ENetAddress remote=mEvent.peer->address;
> char ip[256];
> enet_address_get_host_ip(&remote,ip,256);
> ELOG("ip: %s has been connected, NO.: %d  ,port:  %d",ip,num,remote.port);
> mEvent.peer->data=(void*)num++;
> ELOG("user data: %d",mEvent.data);
> if(NULL == mPeer)
> mPeer = mEvent.peer;
> mConnect = true;
> if(safety)
> GlobalThreadLock.Unlock();
> }
> }
> else if(mEvent.type==ENET_EVENT_TYPE_RECEIVE)
> {
> if(safety)
> GlobalThreadLock.Lock();
>
> if (mRecvBuffer.isFull())
> {
> DequeueRecvBuf();
> }
>
> PacketBuffer* packet = new PacketBuffer;
> packet->flags = 0;
> packet->buf.push((const char*)mEvent.packet->data
> ,mEvent.packet->dataLength);
> mRecvBuffer.enqueue(packet);
>
> enet_packet_destroy(mEvent.packet);
>
> if(safety)
> GlobalThreadLock.Unlock();
> }
> else if(mEvent.type==ENET_EVENT_TYPE_DISCONNECT)
> {
> ENetAddress remote=mEvent.peer->address;
> char ip[256];
> enet_address_get_host_ip(&remote,ip,256);
> if(mType == CLIENT)
> {
> ELOG("NO. %d remote has closed connection",mEvent.peer->data);
> if (!mInitiative)
> {
> mConnect = false;
> CallBack(NET_DisConnectWithServer,ip);
> }
> }
> else if(mType == SERVER)
> {
> CallBack(NET_ClientDisConnect,ip);
> ELOG("NO. %d remote has closed connection",mEvent.peer->data);
> }
> }
> }
>
>
> 2013/5/25 Payton Turnage <paytonturnage at gmail.com>
>>
>> Can you post a block of relevant code or link to a gist? Also, note that
>> enet_peer_send does not actually send anything, but just queues it. If it
>> returns 0 it means the packet was successfully queued, and enet_host_service
>> will send it on the next opportunity.
>>
>>
>> On Thu, May 23, 2013 at 11:22 PM, zxz3121 at gmail.com <zxz3121 at gmail.com>
>> wrote:
>>>
>>> I got a issue recently ,it happened randomly,but the probability is very
>>> small。
>>> when I created a client and connect to server success,send and receive is
>>> all normal,but the client suddenly can`t send the buffer at a moment and
>>> still can receive buf,I check the enet_peer_send function it return 0 ,it`s
>>> means sending normal.,I wonder if the issue is caused by server
>>>
>>> ________________________________
>>> zxz3121 at gmail.com
>>>
>>> _______________________________________________
>>> ENet-discuss mailing list
>>> ENet-discuss at cubik.org
>>> http://lists.cubik.org/mailman/listinfo/enet-discuss
>>>
>>
>
>
> _______________________________________________
> ENet-discuss mailing list
> ENet-discuss at cubik.org
> http://lists.cubik.org/mailman/listinfo/enet-discuss
>


More information about the ENet-discuss mailing list