想用select 模型实现TCP并发服务器,大家指点一下啊 谢谢了
想用select 模型实现TCP并发服务器,大家能给我点思路吗?谢谢
[解决办法]
详细请参考Unix 网络编程第一卷
上面讲select原理很清楚,还有许多并发模型
[解决办法]
思路就是了解Select模型的的实质,和阻塞模型的区别.然后找点例子看看就OK了.网上这种例子要铺出来了.
楼主的问题还是过于笼统了
[解决办法]
// select mode
#define SELECT_MODE_READY 0x001
#define SELECT_MODE_WRITE0x002
// select return codes
#define SELECT_STATE_READY 0
#define SELECT_STATE_ERROR 1
#define SELECT_STATE_ABORTED 2
#define SELECT_STATE_TIMEOUT 3
#ifdef WIN32
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#pragma warning(disable:4786)
#pragma warning(disable:4996)
#define SocketLen int
#else
//network
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <netdb.h>
#endif
int CMySocket::BlockReceive(SOCKET sock, LPCSTR pBuffer, int readSize, int nTimeOut)
{
int selectState;
int recvSize;
selectState = Select(sock, SELECT_MODE_READY, nTimeOut);
if (SELECT_STATE_TIMEOUT == selectState)
return 0;
if (SELECT_STATE_READY == selectState)
{
recvSize = recv(sock, (char*)pBuffer, readSize, 0);
if (recvSize <= 0)
return -1;
return recvSize;
}
return -1;
}
int CMySocket::BlockSend(SOCKET sock, LPCSTR pBuffer, int writeSize, int nTimeOut)
{
int selectState = 0;
int sendSize = 0;
selectState = Select(sock, SELECT_MODE_WRITE, nTimeOut);
if (selectState == SELECT_STATE_TIMEOUT)
return 0;
if (selectState == SELECT_STATE_READY)
{
sendSize = send(sock, (char*)pBuffer, writeSize, 0);
if (sendSize <= 0)
return -1;
return sendSize;
}
return -1;
}
{
printf("WSASocket errors!\n");
return;
}
SOCKADDR_IN addrSvr;
ZeroMemory(&addrSvr, sizeof(SOCKADDR_IN));
addrSvr.sin_family = AF_INET;
addrSvr.sin_port = htons(7000);
addrSvr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
int nRet = bind(sockSvr, (SOCKADDR*)&addrSvr, sizeof(SOCKADDR));
if(SOCKET_ERROR == nRet)
{
printf("bind errors!\n");
return;
}
nRet = listen(sockSvr, 500);//500:max number of connect request
if(SOCKET_ERROR == nRet)
{
printf("listen errors!\n");
return;
}
HANDLE hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0);
if(!hCompletionPort)
{
printf("CreateIoCompletionPort errors!\n");
return;
}
SYSTEM_INFO SystemInfo;
UINT i = 0;
DWORD dwThreadID = 0;
GetSystemInfo(&SystemInfo);
for(i=0; i<SystemInfo.dwNumberOfProcessors*2; i++)
{
HANDLE ThreadHandle = CreateThread(NULL, 0, ServerWorkerThread, hCompletionPort, 0, &dwThreadID);
if(ThreadHandle == NULL)
{
printf("CreateThread() failed with error %d\n", GetLastError());
return;
}
CloseHandle(ThreadHandle);
}
while(true)
{
SOCKADDR_IN addrAccept;
ZeroMemory(&addrAccept, sizeof(SOCKADDR_IN));
int nSockLen = sizeof(SOCKADDR);
SOCKET sockAccept = WSAAccept(sockSvr, (SOCKADDR*)&addrAccept, &nSockLen, 0, 0);
if(INVALID_SOCKET == sockSvr)
{
printf("WSAAccept errors!\n");
return;
}
if(NULL==CreateIoCompletionPort((HANDLE)sockAccept, hCompletionPort, (DWORD)sockSvr, 0))
{
printf("CreateIoCompletionPort errors!\n");
return;
}
OVERLAPPEDPLUS* pOlp = new OVERLAPPEDPLUS;
ZeroMemory(pOlp, sizeof(OVERLAPPEDPLUS));
ZeroMemory(&(pOlp->ol), sizeof(OVERLAPPED));
pOlp->socket = sockAccept;
pOlp->dwFlags = 0;
pOlp->wsaBuf.buf = pOlp->pBuf;
pOlp->wsaBuf.len = 1000;
pOlp->nOpCode = FD_READ;
nRet = WSARecv(pOlp->socket, &(pOlp->wsaBuf), 1, &(pOlp->dwBytes), &(pOlp->dwFlags), &(pOlp->ol), NULL);
if(SOCKET_ERROR == nRet)
{
if(WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
return;
}
}
}
while(TRUE)
{// 给其他线程执行机会
Sleep(1);
}
getchar();
return;
}
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
HANDLE hCompletionPort = (HANDLE) CompletionPortID;
void* re;
DWORD berByte;
OVERLAPPED* pOl;
while(TRUE)
{
BOOL bRet = GetQueuedCompletionStatus(hCompletionPort, &berByte, (LPDWORD)&re, (LPOVERLAPPED*)&pOl, INFINITE);
if(!bRet)
{
printf("GetQueuedCompletionStatus failed with error %d\n", GetLastError());
return FALSE;
}
if(0 == berByte)
{
printf("DGFDGDGF\n");
return FALSE;
}
OVERLAPPEDPLUS* pOlp = (OVERLAPPEDPLUS*) pOl;
switch(pOlp->nOpCode)
{
case FD_READ:
printf("%s\n", pOlp->wsaBuf.buf);
break;
default:
printf("no data!!\n");
}
pOlp->nOpCode = FD_READ;
WSARecv(pOlp->socket, &(pOlp->wsaBuf), 1, &(pOlp->dwBytes), &(pOlp->dwFlags), &(pOlp->ol), NULL);
}
return TRUE;
}