本人菜鸟,大神飘过。。
如有什么不对的地方,请大家多多指正过来。再次感谢!!!
就我所知的异步通讯有:
SELECT,WSAAynsSelect,,WSAEventSelect, 重叠I/O,完成端口。
SELECT 的核心思想就是你要懂fd_set结构。 而对此结构的几个操作方法:FD_ZERO, FD_SET和FD_ISSET。
其大概的流程应该是:
1)申明一个fd_set对象,如 fd_set fd1;
2)在循环中,调用FD_ZERO(fd1)。从文字可以看出,主要作用是把结构清零!
3)调用FD_SET(s,&fd1)。主要作用是把我们的套接字s放到结构体中。
4)调用select函数。检查是否有读写事件。。
5)调用FD_ISSET(s,fd1),查看是否有读写事件。如果为真,则有事件,操作recv/send
WSAAynsSelect的核心思想就是系统帮我监听我们要求监听的事件,然后用WINDOWS消息告诉我们。
具体可以参考:http://blog.csdn.net/yanheifeng715000/article/details/6593303
WSAEventSelect的核心思想就是把每个套接字绑定一个EVENT事件,当对应的套接字有读写操作时,就会触发对应的事件。然后进行操作!
具体参考:http://blog.csdn.net/wanjingwei/article/details/4306609
而重叠I/O的核心事件是利用OVERLAPPED结构,而该对象我们主要关心的是hEvent成员。该成员绑定一个事件,可用WSACreateEvent、CreateEvent。
每个对象套接字都会绑定一个OVERLAPPED结构,当有读写事件时,hEvent为有信号状态。
可用代码在:http://download.csdn.net/detail/magedhenary/7519573
好了,其实我并不太会说,直接上代码:
class LappedSocket
{
public:
LappedSocket()
: m_sock(NULL)
, m_pbuf(NULL)
, m_len(0)
, m_oper(OPER_SOCKET_EMPTY){}
LappedSocket(SOCKET sock, int nlen)
:m_oper(OPER_SOCKET_EMPTY){
m_sock = sock;
m_pbuf = new char[nlen];
memset(m_pbuf, 0, nlen);
m_len = nlen;
m_overlapped.hEvent = ::WSACreateEvent();
}
~LappedSocket(){
if (m_sock != NULL){
closesocket(m_sock);
m_sock = NULL;
}
if (m_pbuf != NULL){
delete[] m_pbuf;
m_pbuf = NULL;
}
m_len = 0;
m_oper = OPER_SOCKET_EMPTY;
}
bool operator ==(const LappedSocket& socket){
if (this->m_sock == socket.m_sock
&& this->m_len == socket.m_len
&& this->m_oper == socket.m_oper
&& strcmp(this->m_pbuf, socket.m_pbuf) == 0)
return true;
return false;
}
public:
int RecvLapped();
int SendLapped();
public:
SOCKET m_sock; // socket information
OVERLAPPED m_overlapped;// bind i/o
char* m_pbuf;// buffer
int m_len;// length
int m_oper;// operation
};
该类主要是为了封装SOCKET,与OVERLAPPED结构。
class LappedServer
{
public:
LappedServer(){
m_sockListen = NULL;
m_nport = 0;
m_blisten = false;
memset(m_saddr, 0, 256);
}
~LappedServer(){ CloseServer(); }
void CloseServer();
void StartServer(int nport, char* paddr, int nlisten=5);
protected:
bool CreateServer();
static unsigned _stdcall _StartServer(void* pinfor);
private:
SOCKET m_sockListen;
int m_nlisten;
int m_nport;
char m_saddr[256];
bool m_blisten;
HANDLE m_handle;
};
该类主要封装一个服务器,调用StartServer函数即可启动服务器监听。
class ManagerSocket
{
public:
ManagerSocket();
~ManagerSocket();
public:
int GetSize(){
return m_lsSock.size();
}
bool InsertSocket(SOCKET sock);
bool PostRecv(LappedSocket* psock);
bool PostSend(LappedSocket* psock);
void StartThread();
protected:
void ResetEventArray();
// thread operation
static unsigned _stdcall StartOperation(void* pinfor);
bool OperationSocket(int index);
public:
deque<LappedSocket*> m_lsSock;
vector<HANDLE>m_lsEvent;
HANDLE m_hAcceptEvent;
bool m_bThread;
HANDLE m_threadOper;
};
该类主要是管理服务器监听到的SOCKET。查看每个SOCKET的读写事件。。
可用代码在:http://download.csdn.net/detail/magedhenary/7519573
今天到此为止!改天在整整完成端口的类出来跟大家讨论讨论。
技术有限,如有什么好的建议欢迎大家跟我交流,指正!