SendDataThread()函数完成客户端数据发送的功能。该函数外层是一个while循环体。当客户端与服务器处于连接状态时bConnecting为TRUE,该函数处于循环状态。在循环中调用Sleep()函数使该线程睡眠TIMEFOR_THREAD_SLEEP时间。
当接收到发送数据的通知后,bSendData为TRUE,调用send()函数将发送缓冲区的数据发送出去。当数据发送完毕后,将bSendData变量值修改为FALSE。该线程等待下次数据发送。
下面说明,一种客户端被动关闭的情况。
q 主线程通知发送数据线程发送数据。然后,调用WaitForSingleObject()函数,等待显示数据结果hEventShowDataResult事件对象。而此时,由于某种原因客户端与服务器的连接断开,那么主线程被阻塞于该函数。
q 为此,在发送数据线程,当send()函数返回网络连接错误时,设置bConnecting变量为FALSE。同时,设置hEventShowDataResult事件对象为有信号状态。那么,主线程的WaitForSingleObject()函数会立即返回。并根据bConnecting变量值,判断此时与服务器连接已经断开。然后,主线程等待数据发送和接收线程退出。
SendDataThread()函数的程序清单如下。
#define TIMEFOR_THREAD_SLEEP 500 //线程睡眠时间
/**
* 发送数据线程
*/
DWORD __stdcall SendDataThread(void* pParam)
{
while(bConnecting) //连接状态
{
if (bSendData) //发送数据
{
EnterCriticalSection(&csSend); //进入临界区
for (;;)
{
int nBuflen = ((phdr)(bufSend.buf))->len;
int val = send(sClient, bufSend.buf, nBuflen,0);
//处理返回错误
if (SOCKET_ERROR == val)
{
int nErrCode = WSAGetLastError();
if(WSAEWOULDBLOCK == nErrCode) //发送缓冲区不可用
{
continue; //继续循环
}else {
LeaveCriticalSection(&csSend); //离开临界区
bConnecting = FALSE; //断开状态
SetEvent(hEventShowDataResult); //通知主线程,防止在无限期的等待返回结果。
return 0;
}
}
bSendData = FALSE; //发送状态
break; //跳出for循环
}
LeaveCriticalSection(&csSend); //离开临界区
}
Sleep(TIMEFOR_THREAD_SLEEP); //线程睡眠
}
return 0;
}