想用select 模型实现TCP并发服务器,大家指点一下啊 谢谢了
想用select 模型实现TCP并发服务器,大家能给我点思路吗?谢谢
[解决办法]
详细请参考Unix 网络编程第一卷
上面讲select原理很清楚,还有许多并发模型
[解决办法]
思路就是了解Select模型的的实质,和阻塞模型的区别.然后找点例子看看就OK了.网上这种例子要铺出来了.
楼主的问题还是过于笼统了
[解决办法]
- C/C++ code
// 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;
}
[解决办法]
select的网络吞吐量和性能一般,优点是可以跨平台.像我上面的代码,就是平台兼容的.设计TCP服务器,如果连接量和吞吐量不大,就以用select模型,还需要一个线程用来ACCEPT连接,然后每接受了一个连接,再开一线程接收数据,循环调用上面的BlockReceive函数.
[解决办法]
看下这个资源 http://download.csdn.net/source/2742482
[解决办法]
用socket IOCP完成端口模型
// testiocp.cpp : Defines the entry point for the console application.
//
#include "StdAfx.h"
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
typedef struct _OVERLAPPEDPLUS
{
OVERLAPPED ol;
SOCKET socket;
int nOpCode;
WSABUF wsaBuf;
DWORD dwFlags;
DWORD dwBytes;
char pBuf[1000];
}OVERLAPPEDPLUS, *POVERLAPPEDPLUS;
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
printf("WSAStartup errors!\n");
return;
}
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 )
{
WSACleanup( );
return;
}
SOCKET sockSvr = WSASocket(AF_INET, SOCK_STREAM, 0, 0, 0, WSA_FLAG_OVERLAPPED);
if(INVALID_SOCKET == sockSvr)
{
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;
}