我的服务程序在一个客户端接入以后就开一个接收线程,负责接收它的数据。
在此期间客户机保持和服务器的连接。实际运行时,发现这个接收线程一运行,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;
}
在此期间客户机保持和服务器的连接。实际运行时,发现这个接收线程一运行,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;
}
解决方案 »
- 关于 wsock32.dll
- 菜鸟求助几个简单的问题.CEdit限制字符数.CComboBox禁止编辑.CWebBrowser屏蔽鼠标右键
- DirectShow的IMediaSeeking::SetPositions后我的SourceFilter怎么样才能在媒体文件中定位以便读入??
- 如何通过程序获取另外一个窗口上某个控件的资源ID
- 帮帮忙啊.如何在VC6上使用GDI+库啊?哪有下载啊?
- 进程退出时,该进程打开的socket套接字是否会自动关闭,该进程加载的dll是否会自动卸载?
- 某个表里有1亿条记录,每秒写2000次,读10万次,
- 基于Dialog的,如何在启动时可以有启动画面(最好详细一点),另外。。
- 如何在我的DLL当中,获得窗口句柄?
- 一个关于基于MFC的单文档桌面应用程序
- 调用api函数使用双缓冲方式在窗口中画线时的问题
- 怎么样修改list里item的label
另一个方法是,是用事件方式。你的接收处理方法有问题
if (ret == SOCKET_ERROR)
{
printf("Select() Socket error: %d..\n",GetLastError ());
continue;//很显然,这里需要Getlastererro看看一下错误原因,这样,在不需要的时候,跳出循环。
}
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;
}
{
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.
或者用消息EVENT通知。
WHILE( )
循环对CPU的消耗太巨大了,一定要有措施来主动交出CPU时间段