大家的接收线程是怎么实现的啊?怎么我的接收线程消耗CPU资源这么大啊?
我的服务程序在一个客户端接入以后就开一个接收线程,负责接收它的数据。
在此期间客户机保持和服务器的连接。
实际运行时,发现这个接收线程一运行,CPU利用率达到100%,根本接收不了其他的连接,请问大家怎么处理接收线程的?怎么改善接收线程的性能?
// 接收数据线程如下:
DWORD WINAPI RecvThread(LPVOID lParam)
{
int Socket;
Socket= (int )lParam;
fd_set fdRead;
struct timeval tmvTimeout={0L,100L};
char RecvBuf[256];
while (TRUE)
{
// 初始化
FD_ZERO(&fdRead);
FD_SET(Socket,&fdRead);
int ret = select(0,&fdRead,NULL,NULL,&tmvTimeout);
if (ret == SOCKET_ERROR)
{
printf("Select() Socket error: %d..\n",GetLastError ());
continue;
}
else if (ret > 0)
{
if (FD_ISSET(Socket,&fdRead))
{ // 有数据可读
nRecv= recv (Socket, RecvBuf, sizeof( RecvBuf), 0);
if (nRecv == SOCKET_ERROR)
{ // 读数据出错
printf("Recv socket error: %d..\n",GetLastError());
}
else
if (nRecv == 0)
{ // 客户端断开连接
printf("remote socket closed..\n");
closesocket(Socket);
break;
}
// 数据读入成功,做数据处理
printf("Successfully receive %d bytes..\n"),nRecv);
ProcessData(RecvBuf);
}
}
}
printf("Recv thread exit with 0..\n");
return 0;
}
问题点数:20、回复次数:10Top
1 楼B2China(海陆空天电磁)回复于 2004-05-02 13:40:52 得分 0
我是用whle(true),这个大循环来不停的监视客户端连接是否有数据可读的,可能是由于这个原因导致CPU利用率高的惊人。Top
2 楼xuweiqun(打雷啦)回复于 2004-05-02 14:20:31 得分 1
我在串口通信中使用的是事件的触发方式,所以只有数据来的时候,才触发接收,Top
3 楼elusion(落)回复于 2004-05-02 14:22:58 得分 1
sleep一下Top
4 楼wwwllg(野蛮人)回复于 2004-05-02 15:07:52 得分 5
一种方法是加sleep(1).在while里面。
另一个方法是,是用事件方式。
你的接收处理方法有问题
if (ret == SOCKET_ERROR)
{
printf("Select() Socket error: %d..\n",GetLastError ());
continue;//很显然,这里需要Getlastererro看看一下错误原因,这样,在不需要的时候,跳出循环。
}
Top
5 楼max_xy(夏平生)回复于 2004-05-02 18:55:50 得分 1
楼上的,请问怎么样处理select错误呢,按照您的意思。给点代码如何Top
6 楼max_xy(夏平生)回复于 2004-05-02 20:02:25 得分 0
我的线程加了SLEEP,cpu利用率大概20%.但是假如一个客户端需要联接很多个客户端,每个客户端对服务端的联接都使用一个线程的话,CPU的利用率就会很高。不知道能不能不用while而实现同样的功能。Top
7 楼truewq(aibieli)回复于 2004-05-02 20:22:09 得分 4
我也是用While实现的,不过我只是在监听网络,代码差不多你看一下嘛,刚开始我也是CPU占用很高,后来加了一个return 就好了:
DWORD WINAPI LoopScanThread(LPVOID lpparam)
{
SOCKET ListenSocket=(SOCKET)lpparam;
sockaddr_in send;
int sendlen=sizeof(send);
CString aa2="----接收方最大允许连接数为10----";
AfxGetMainWnd()->SendMessageToDescendants(WM_LISTBOX,(WPARAM)aa2.GetBuffer(0),1);
aa2.ReleaseBuffer();
//接收方允许最大的连结数是10
int rc=listen(ListenSocket,10);
if(rc==SOCKET_ERROR)
{
CString a5="----创建监听socket失败,请检查网络后重试----";
AfxGetMainWnd()->SendMessageToDescendants(WM_LISTBOX,(WPARAM)a5.GetBuffer(0),1);
a5.ReleaseBuffer();
::MessageBeep(MB_ICONHAND);
return 0;
}
CString aa3="----创建监听socket成功,开始监听网络----";
AfxGetMainWnd()->SendMessageToDescendants(WM_LISTBOX,(WPARAM)aa3.GetBuffer(0),1);
aa3.ReleaseBuffer();
::MessageBeep(MB_ICONASTERISK);
while(1)
{
SOCKET ConnectSocket;
ConnectSocket=accept(ListenSocket,(sockaddr*)&send,&sendlen);
if(ConnectSocket==INVALID_SOCKET)
{
CString a="----接收发送方请求失败----";
AfxGetMainWnd()->SendMessageToDescendants(WM_LISTBOX,(WPARAM)a.GetBuffer(0),1);
a.ReleaseBuffer();
::MessageBeep(MB_ICONHAND);
return -1;
}
CString a="----接收请求成功,连接已经建立----";
AfxGetMainWnd()->SendMessageToDescendants(WM_LISTBOX,(WPARAM)a.GetBuffer(0),1);
a.ReleaseBuffer();
//直到accept()成切返回,然后进入别一个线程,来接收文件消息
DWORD dwThread1;
::CreateThread(NULL,0,GetFileInfoThread,(LPVOID)ConnectSocket,0,&dwThread1);
}
return 0;
}Top
8 楼max_xy(夏平生)回复于 2004-05-02 21:07:30 得分 1
刚刚觉得用SETTIMER來做,不用while循环。不知道cpu会不会降低一点。来做个测试。Top
9 楼wwwllg(野蛮人)回复于 2004-05-03 17:33:26 得分 5
BOOL CClientOverlappedSock::OnRead()
{
if(!IsConnected())
return false;
DWORD dwTransbit = 0;
DWORD Resv = 0;
DWORD dwFlag = 0;
WSABUF buffer;
BOOL bQuery = false;
int state = 0;
bQuery = WSAGetOverlappedResult( m_RecSocket, &ConnectedSocketOverlapped,
&dwTransbit,false,&dwFlag);
if(bQuery)
{
if(dwTransbit == 0)
{
OnClose();
return true;
}
while(1)
{
if( rPag.len - sizeof(PAG) == DataRes)
{
////
Work();
Reset();
////
buffer.buf = (char*)& rPag;
buffer.len = sizeof(PAG);
state = WSARecv( m_RecSocket,&buffer,1,&Resv,
&dwFlag, &ConnectedSocketOverlapped,NULL);
if(state == 0)
{
continue;
}else
{
DWORD err = WSAGetLastError();
if(err != WSA_IO_PENDING)
{
TRACE1("erro code1 %d\n",err);
OnClose();
return false;
}else
{
if(ERROR_IO_PENDING == err)
{
return true;
}
}
}
}else
if( rPag.len - sizeof(PAG) - DataRes > 0)
{
if(!m_bReadPending)
{
if(buff == NULL)
{
buff = new char [ rPag.len - sizeof(PAG)];
memset( buff,0, rPag.len - sizeof(PAG));
buffer.buf = buff;
buffer.len = rPag.len - sizeof(PAG);
}
Resv = 0;
buffer.len = rPag.len - sizeof(PAG) - DataRes;
buffer.buf = buff + DataRes;
state = WSARecv( m_RecSocket,&buffer,1,&Resv,
&dwFlag, &ConnectedSocketOverlapped,NULL);
if(state == 0)
{
DataRes+=Resv;
continue;
}else
{
DWORD err = WSAGetLastError();
if(err != WSA_IO_PENDING)
{
TRACE1("erro code2 %d\n",err);
OnClose();
return false;
}else
{
if(ERROR_IO_PENDING == err)
{
m_bReadPending = true;
return true;
}
}
}
}else
{
DataRes+=dwTransbit;
}
}
if(!IsConnected())
return 0;
Sleep(1);
TRACE1("RES DATA IS %u\n",DataRes);
}
}else
{
DWORD err = WSAGetLastError();
if(err != ERROR_IO_INCOMPLETE)
{
OnClose();
TRACE1("erro code3 %d\n",err);
return false;
}else
return true;
}
return true;
}
吐血回贴!
当没有数据来时,根本不占用cpu.
Top
10 楼danscort2000(danscort.yu)回复于 2004-05-04 16:58:44 得分 2
加SLEEP( )控制
或者用消息EVENT通知。
WHILE( )
循环对CPU的消耗太巨大了,一定要有措施来主动交出CPU时间段Top




