模仿仿捷的《Win32多线程程序设计》这本书的例子,可工作线程一直无效。,由于客户端发送的是一结构体,该结构体的前8个字节是消息类型和后面的消息长度,我得先接收这8个字节,再觉得下一步的接收,所以我没采用投递WSARecv、WSASend那种一次全部接收的方式#include <iostream>
#include <tchar.h>
using namespace std ;#include <WinSock2.h>
#pragma comment( lib, "Ws2_32.lib" )HANDLE g_hIOCompletionPort = NULL ;
struct ContextKey
{
SOCKET socket;
OVERLAPPED olin;
char buffer[8];//用于接收消息头
OVERLAPPED olout ;
};void IssueRead(struct ContextKey *pCntx)
{
BOOL bResult;
int err;
int numRead; err = recv(pCntx->socket ,pCntx->buffer ,8 ,0 ) ;
if ( err> 0)
{
cout<<pCntx->buffer ; //获得消息头
cout<<"\n";
//...
//再选用合适的结构体接收后面的消息内容
}
}
DWORD WINAPI WorkerThread(LPVOID lParam)
{
DWORD dwStatus = 0; DWORD dwBytesTransfered = 0; LPOVERLAPPED pOverlapped ;
ContextKey *pContextKey ;
while ( true )
{
BOOL bReturn = GetQueuedCompletionStatus(
g_hIOCompletionPort,
&dwBytesTransfered,
(LPDWORD)&pContextKey,
&pOverlapped,
INFINITE);
if (bReturn == FALSE && pOverlapped == NULL )
{
cout<<"GetQueuedCompletionStatus error\n";
// break ;
NULL ;
}
else
if( bReturn == FALSE&& pOverlapped != NULL )
{
// This happens occasionally instead of
// end-of-file. Not sure why.
closesocket(pContextKey->socket);
delete pContextKey ;
cout<<"用户非正常退出\n";
// break ;
}
else
if ( dwBytesTransfered == 0 )
{
closesocket( pContextKey->socket ) ;
delete pContextKey ;
cout<<"用户正常退出\n";
// break ;
}
else
{
IssueRead(pContextKey) ;
//cout<<pContextKey->buffer ;
cout<<"\n";
}
Sleep(10);
}
return dwStatus ;
}
int main()
{ DWORD dwStatus = 0 ; WSAData WsaData ;
DWORD dwThreadID = 0 ;
SOCKET SocketServer = INVALID_SOCKET ;
SOCKET SocketAccept = INVALID_SOCKET ;
SOCKADDR_IN addrLocal={0};
SOCKADDR_IN addrRemote = {0} ;
int naddrLen=sizeof(addrRemote); BOOL bReuseAddr = TRUE ;
fd_set fdRead ;
timeval time ;
time.tv_sec = 1 ;
time.tv_usec = 0 ;
int iReturnValue = 0 ;
int nTimeOut= 6*1000 ; do
{
dwStatus =WSAStartup( MAKEWORD( 2, 0 ), &WsaData ) ;
if ( dwStatus != 0 )
{
dwStatus = WSAGetLastError() ;
break ;
} SocketServer = WSASocket( AF_INET ,SOCK_STREAM , IPPROTO_TCP , 0 , 0 , 0 ) ;
if ( INVALID_SOCKET == SocketServer )
{
dwStatus = WSAGetLastError() ;
break ;
}
if ( SOCKET_ERROR == setsockopt( SocketServer ,SOL_SOCKET , SO_RCVTIMEO ,(char*)&nTimeOut , sizeof(nTimeOut) ) )
{
closesocket( SocketServer ) ;
dwStatus = WSAGetLastError() ;
break ;
}
if ( SOCKET_ERROR == setsockopt( SocketServer , SOL_SOCKET , SO_REUSEADDR , (char *)&bReuseAddr , sizeof( bool ) ) )
{
closesocket( SocketServer ) ;
dwStatus = WSAGetLastError() ;
break ;
}
addrLocal.sin_family = AF_INET ;
addrLocal.sin_port = ( 9998 ) ;
addrLocal.sin_addr.S_un.S_addr = INADDR_ANY ;//inet_addr("127.0.0.1")
if ( SOCKET_ERROR == bind( SocketServer , ( struct sockaddr * )&addrLocal , sizeof( addrLocal ) ) )
{
closesocket( SocketServer ) ;
dwStatus = WSAGetLastError() ;
break ;
} if ( SOCKET_ERROR == listen( SocketServer , 5 ) )
{
closesocket( SocketServer ) ;
dwStatus = WSAGetLastError() ;
break ;
} DWORD nThreadID;
//Create worker threads for (int ii = 0; ii < 6; ii++)
{
CreateThread(0, 0, WorkerThread,
(void *)(ii+1), 0, &nThreadID);
} SocketAccept = accept( SocketServer , (struct sockaddr*)&addrRemote ,&naddrLen );
if ( INVALID_SOCKET == SocketAccept )
{
closesocket( SocketServer ) ;
dwStatus = WSAGetLastError() ;
break ;
}
g_hIOCompletionPort =
CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0 ); if ( NULL == g_hIOCompletionPort)
{
printf("\nError occurred while creating IOCP: %d.",
WSAGetLastError());
dwStatus = WSAGetLastError() ;
break ;
} ContextKey *pContextKey = new ContextKey ;
//ZeroMemory(&pContextKey , sizeof(ContextKey) ) ;
pContextKey->socket = SocketAccept ;
pContextKey->olout.hEvent = CreateEvent( NULL ,TRUE ,FALSE , 0 ) ;
pContextKey->olout.hEvent = (HANDLE)( (DWORD)pContextKey->olout.hEvent|0x1 ) ; CreateIoCompletionPort(
(HANDLE)pContextKey->socket ,
g_hIOCompletionPort ,
(DWORD)pContextKey ,
0) ; IssueRead(pContextKey) ;//第一次读取
}while(FALSE) ; getchar() ;
WSACleanup() ;
return 0;
}
#include <tchar.h>
using namespace std ;#include <WinSock2.h>
#pragma comment( lib, "Ws2_32.lib" )HANDLE g_hIOCompletionPort = NULL ;
struct ContextKey
{
SOCKET socket;
OVERLAPPED olin;
char buffer[8];//用于接收消息头
OVERLAPPED olout ;
};void IssueRead(struct ContextKey *pCntx)
{
BOOL bResult;
int err;
int numRead; err = recv(pCntx->socket ,pCntx->buffer ,8 ,0 ) ;
if ( err> 0)
{
cout<<pCntx->buffer ; //获得消息头
cout<<"\n";
//...
//再选用合适的结构体接收后面的消息内容
}
}
DWORD WINAPI WorkerThread(LPVOID lParam)
{
DWORD dwStatus = 0; DWORD dwBytesTransfered = 0; LPOVERLAPPED pOverlapped ;
ContextKey *pContextKey ;
while ( true )
{
BOOL bReturn = GetQueuedCompletionStatus(
g_hIOCompletionPort,
&dwBytesTransfered,
(LPDWORD)&pContextKey,
&pOverlapped,
INFINITE);
if (bReturn == FALSE && pOverlapped == NULL )
{
cout<<"GetQueuedCompletionStatus error\n";
// break ;
NULL ;
}
else
if( bReturn == FALSE&& pOverlapped != NULL )
{
// This happens occasionally instead of
// end-of-file. Not sure why.
closesocket(pContextKey->socket);
delete pContextKey ;
cout<<"用户非正常退出\n";
// break ;
}
else
if ( dwBytesTransfered == 0 )
{
closesocket( pContextKey->socket ) ;
delete pContextKey ;
cout<<"用户正常退出\n";
// break ;
}
else
{
IssueRead(pContextKey) ;
//cout<<pContextKey->buffer ;
cout<<"\n";
}
Sleep(10);
}
return dwStatus ;
}
int main()
{ DWORD dwStatus = 0 ; WSAData WsaData ;
DWORD dwThreadID = 0 ;
SOCKET SocketServer = INVALID_SOCKET ;
SOCKET SocketAccept = INVALID_SOCKET ;
SOCKADDR_IN addrLocal={0};
SOCKADDR_IN addrRemote = {0} ;
int naddrLen=sizeof(addrRemote); BOOL bReuseAddr = TRUE ;
fd_set fdRead ;
timeval time ;
time.tv_sec = 1 ;
time.tv_usec = 0 ;
int iReturnValue = 0 ;
int nTimeOut= 6*1000 ; do
{
dwStatus =WSAStartup( MAKEWORD( 2, 0 ), &WsaData ) ;
if ( dwStatus != 0 )
{
dwStatus = WSAGetLastError() ;
break ;
} SocketServer = WSASocket( AF_INET ,SOCK_STREAM , IPPROTO_TCP , 0 , 0 , 0 ) ;
if ( INVALID_SOCKET == SocketServer )
{
dwStatus = WSAGetLastError() ;
break ;
}
if ( SOCKET_ERROR == setsockopt( SocketServer ,SOL_SOCKET , SO_RCVTIMEO ,(char*)&nTimeOut , sizeof(nTimeOut) ) )
{
closesocket( SocketServer ) ;
dwStatus = WSAGetLastError() ;
break ;
}
if ( SOCKET_ERROR == setsockopt( SocketServer , SOL_SOCKET , SO_REUSEADDR , (char *)&bReuseAddr , sizeof( bool ) ) )
{
closesocket( SocketServer ) ;
dwStatus = WSAGetLastError() ;
break ;
}
addrLocal.sin_family = AF_INET ;
addrLocal.sin_port = ( 9998 ) ;
addrLocal.sin_addr.S_un.S_addr = INADDR_ANY ;//inet_addr("127.0.0.1")
if ( SOCKET_ERROR == bind( SocketServer , ( struct sockaddr * )&addrLocal , sizeof( addrLocal ) ) )
{
closesocket( SocketServer ) ;
dwStatus = WSAGetLastError() ;
break ;
} if ( SOCKET_ERROR == listen( SocketServer , 5 ) )
{
closesocket( SocketServer ) ;
dwStatus = WSAGetLastError() ;
break ;
} DWORD nThreadID;
//Create worker threads for (int ii = 0; ii < 6; ii++)
{
CreateThread(0, 0, WorkerThread,
(void *)(ii+1), 0, &nThreadID);
} SocketAccept = accept( SocketServer , (struct sockaddr*)&addrRemote ,&naddrLen );
if ( INVALID_SOCKET == SocketAccept )
{
closesocket( SocketServer ) ;
dwStatus = WSAGetLastError() ;
break ;
}
g_hIOCompletionPort =
CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0 ); if ( NULL == g_hIOCompletionPort)
{
printf("\nError occurred while creating IOCP: %d.",
WSAGetLastError());
dwStatus = WSAGetLastError() ;
break ;
} ContextKey *pContextKey = new ContextKey ;
//ZeroMemory(&pContextKey , sizeof(ContextKey) ) ;
pContextKey->socket = SocketAccept ;
pContextKey->olout.hEvent = CreateEvent( NULL ,TRUE ,FALSE , 0 ) ;
pContextKey->olout.hEvent = (HANDLE)( (DWORD)pContextKey->olout.hEvent|0x1 ) ; CreateIoCompletionPort(
(HANDLE)pContextKey->socket ,
g_hIOCompletionPort ,
(DWORD)pContextKey ,
0) ; IssueRead(pContextKey) ;//第一次读取
}while(FALSE) ; getchar() ;
WSACleanup() ;
return 0;
}
解决方案 »
- 在拖动CListCtrl的时候刷屏刷的厉害
- winpcap文档中找不到PacketOpenAdapter函数解释
- 有人用过zlib么?
- 如何将CString 转换成char数组
- 求助在LINUX下的程序运行的命令问题
- 怎么样在client端用VC以http方式访问连接server的端?
- Assertion Failed的问题究竟该怎么查?
- 无法立即完成一个非阻挡性套接字操作
- ●●(已经第三贴了!!)有关 new 视图的一个问题,希望高手相助!! ●●
- 编译一个CPP文件时,出现这个错误怎么办?
- VC 连接 SQL SERVER/oracle等数据库时采用哪种方式效率要高?
- 关于用_RecordsetPtr 的问题。。。请教
typedef struct Book
{
char szName[64];
int size;
char szWorker[64];
}Book;typedef struct BookPacket
{
int type;
BookPacket book;
}BookPacket;typedef struct Person
{
char szName[64];
int iage;
}Person;
typedef struct PersonPacket
{
int type;
Person person;
}PersonPacket;客户端会一次性发送PersonPacket或者BookPacket 这样的结构体包过来,
我分两次来接收客户端的包
我想先得到int type这一个字段,然后,再根据type区别出是该再接收Book大小还是Person大小的包。
本想先投递一个int大小,然后再投递Book大小或者Person大小
{
char szName[64];
int size;
char szWorker[64];
}Book;typedef struct BookPacket
{
int type;
Book book;
}BookPacket;typedef struct Person
{
char szName[64];
int iage;
}Person;
typedef struct PersonPacket
{
int type;
Person person;
}PersonPacket;客户端会一次性发送PersonPacket或者BookPacket 这样的结构体包过来,
我分两次来接收客户端的包
我想先得到int type这一个字段,然后,再根据type区别出是该再接收Book大小还是Person大小的包。
本想先投递一个int大小,然后再投递Book大小或者Person大小