SOCKET编程进阶之Overlapped IO完成例程模型
来源:互联网 发布:青岛最专业的seo公司 编辑:程序博客网 时间:2024/04/29 11:43
完成例程模型相比与事件通知模型有个很大的优点就是不再受64个消息的限制,一个线程可以同时管理成百上千个socket连接,且保持较高的性能。
完成例程相比与完成端口较为逊色,因为它的性能不能随着系统CPU数量的增长而线程增长,不过在我看来已经很强了,呵呵~!
说白了,这些连接都是由系统来帮你管理的。你只需做的一件事就是:开启一个线程来accept进来的连接,剩下的工作交由系统来处理。而你,则需要提供给系统一个回调函数,发生新的网络事件的时候系统将执行这个函数:
procedure WorkerRoutine( const dwError, cbTransferred : DWORD; const lpOverlapped : LPWSAOVERLAPPED; const dwFlags : DWORD ); stdcall;
然后告诉系统用WorkerRoutine函数处理接收到的数据:
WSARecv( m_socket, @FBuf, 1, dwTemp, dwFlag, @m_overlap, WorkerRoutine );
然后......没有什么然后了,系统什么都给你做了!
源码---------------------------------------------------------------------------------------------
#pragma comment(lib,"ws2_32.lib")
#include <winsock2.h>
#include <stdio.h>
#define DATA_BUFSIZE 1024 // 接收缓冲区大小
#define MAXSESSION 10000 // 最大连接数
typedef struct _SOCKET_INFORMATION {
OVERLAPPED Overlapped;
SOCKET Socket;
WSABUF DataBuf;
DWORD BytesSEND;
DWORD BytesRECV;
} SOCKET_INFORMATION, * LPSOCKET_INFORMATION;
SOCKET ListenSocket = INVALID_SOCKET;
DWORD Flags = 0; // WSARecv的参数
void CALLBACK WorkerRoutine(DWORD Error, DWORD BytesTransferred,LPWSAOVERLAPPED Overlapped, DWORD InFlags);
DWORD WINAPI AcceptThread(LPVOID lpParameter)
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2),&wsaData);
ListenSocket = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,NULL,WSA_FLAG_OVERLAPPED);
SOCKADDR_IN ServerAddr;
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
ServerAddr.sin_port = htons(1234);
bind(ListenSocket,(LPSOCKADDR)&ServerAddr,sizeof(ServerAddr));
listen(ListenSocket,100);
printf("listenning...\n");
SOCKADDR_IN ClientAddr;
int addr_length=sizeof(ClientAddr);
while (TRUE)
{
LPSOCKET_INFORMATION SI = new SOCKET_INFORMATION;
if ((SI->Socket = accept(ListenSocket,(SOCKADDR*)&ClientAddr, &addr_length)) != INVALID_SOCKET)
{
printf("accept ip:%s port:%d\n",inet_ntoa(ClientAddr.sin_addr),ClientAddr.sin_port);
memset(&SI->Overlapped,0,sizeof(WSAOVERLAPPED));
SI->DataBuf.buf = new char[DATA_BUFSIZE];
SI->DataBuf.len = DATA_BUFSIZE;
memset(SI->DataBuf.buf,0,DATA_BUFSIZE);
if(WSARecv(SI->Socket, &SI->DataBuf, 1, &SI->BytesRECV, &Flags, &SI->Overlapped, WorkerRoutine) == SOCKET_ERROR)
{
int err = WSAGetLastError();
if(WSAGetLastError() != WSA_IO_PENDING)
{
printf("disconnect\n");
closesocket(SI->Socket);
delete [] SI->DataBuf.buf;
delete SI;
continue;
}
}
}
}
return FALSE;
}
void CALLBACK WorkerRoutine(DWORD Error, DWORD BytesTransferred, LPWSAOVERLAPPED Overlapped, DWORD InFlags)
{
LPSOCKET_INFORMATION SI = (LPSOCKET_INFORMATION)Overlapped;
if (Error != 0 || BytesTransferred == 0)
{
printf("disconnect\n");
closesocket(SI->Socket);
delete [] SI->DataBuf.buf;
delete SI;
return;
}
//使用数据
printf("call back:%s\n",SI->DataBuf.buf);
memset(SI->DataBuf.buf,0,DATA_BUFSIZE);
if(WSARecv(SI->Socket, &SI->DataBuf, 1, &SI->BytesRECV, &Flags, &SI->Overlapped, WorkerRoutine) == SOCKET_ERROR)
{
int err = WSAGetLastError();
if(WSAGetLastError() != WSA_IO_PENDING)
{
printf("disconnect\n");
closesocket(SI->Socket);
delete [] SI->DataBuf.buf;
delete SI;
return;
}
}
}
void main()
{
HANDLE hThreads = CreateThread(NULL, 0, AcceptThread, NULL, NULL, NULL);
WaitForSingleObject(hThreads,INFINITE);
printf("exit\n");
CloseHandle(hThreads);
}
完成例程相比与完成端口较为逊色,因为它的性能不能随着系统CPU数量的增长而线程增长,不过在我看来已经很强了,呵呵~!
说白了,这些连接都是由系统来帮你管理的。你只需做的一件事就是:开启一个线程来accept进来的连接,剩下的工作交由系统来处理。而你,则需要提供给系统一个回调函数,发生新的网络事件的时候系统将执行这个函数:
procedure WorkerRoutine( const dwError, cbTransferred : DWORD; const lpOverlapped : LPWSAOVERLAPPED; const dwFlags : DWORD ); stdcall;
然后告诉系统用WorkerRoutine函数处理接收到的数据:
WSARecv( m_socket, @FBuf, 1, dwTemp, dwFlag, @m_overlap, WorkerRoutine );
然后......没有什么然后了,系统什么都给你做了!
源码---------------------------------------------------------------------------------------------
#pragma comment(lib,"ws2_32.lib")
#include <winsock2.h>
#include <stdio.h>
#define DATA_BUFSIZE 1024 // 接收缓冲区大小
#define MAXSESSION 10000 // 最大连接数
typedef struct _SOCKET_INFORMATION {
OVERLAPPED Overlapped;
SOCKET Socket;
WSABUF DataBuf;
DWORD BytesSEND;
DWORD BytesRECV;
} SOCKET_INFORMATION, * LPSOCKET_INFORMATION;
SOCKET ListenSocket = INVALID_SOCKET;
DWORD Flags = 0; // WSARecv的参数
void CALLBACK WorkerRoutine(DWORD Error, DWORD BytesTransferred,LPWSAOVERLAPPED Overlapped, DWORD InFlags);
DWORD WINAPI AcceptThread(LPVOID lpParameter)
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2),&wsaData);
ListenSocket = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,NULL,WSA_FLAG_OVERLAPPED);
SOCKADDR_IN ServerAddr;
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
ServerAddr.sin_port = htons(1234);
bind(ListenSocket,(LPSOCKADDR)&ServerAddr,sizeof(ServerAddr));
listen(ListenSocket,100);
printf("listenning...\n");
SOCKADDR_IN ClientAddr;
int addr_length=sizeof(ClientAddr);
while (TRUE)
{
LPSOCKET_INFORMATION SI = new SOCKET_INFORMATION;
if ((SI->Socket = accept(ListenSocket,(SOCKADDR*)&ClientAddr, &addr_length)) != INVALID_SOCKET)
{
printf("accept ip:%s port:%d\n",inet_ntoa(ClientAddr.sin_addr),ClientAddr.sin_port);
memset(&SI->Overlapped,0,sizeof(WSAOVERLAPPED));
SI->DataBuf.buf = new char[DATA_BUFSIZE];
SI->DataBuf.len = DATA_BUFSIZE;
memset(SI->DataBuf.buf,0,DATA_BUFSIZE);
if(WSARecv(SI->Socket, &SI->DataBuf, 1, &SI->BytesRECV, &Flags, &SI->Overlapped, WorkerRoutine) == SOCKET_ERROR)
{
int err = WSAGetLastError();
if(WSAGetLastError() != WSA_IO_PENDING)
{
printf("disconnect\n");
closesocket(SI->Socket);
delete [] SI->DataBuf.buf;
delete SI;
continue;
}
}
}
}
return FALSE;
}
void CALLBACK WorkerRoutine(DWORD Error, DWORD BytesTransferred, LPWSAOVERLAPPED Overlapped, DWORD InFlags)
{
LPSOCKET_INFORMATION SI = (LPSOCKET_INFORMATION)Overlapped;
if (Error != 0 || BytesTransferred == 0)
{
printf("disconnect\n");
closesocket(SI->Socket);
delete [] SI->DataBuf.buf;
delete SI;
return;
}
//使用数据
printf("call back:%s\n",SI->DataBuf.buf);
memset(SI->DataBuf.buf,0,DATA_BUFSIZE);
if(WSARecv(SI->Socket, &SI->DataBuf, 1, &SI->BytesRECV, &Flags, &SI->Overlapped, WorkerRoutine) == SOCKET_ERROR)
{
int err = WSAGetLastError();
if(WSAGetLastError() != WSA_IO_PENDING)
{
printf("disconnect\n");
closesocket(SI->Socket);
delete [] SI->DataBuf.buf;
delete SI;
return;
}
}
}
void main()
{
HANDLE hThreads = CreateThread(NULL, 0, AcceptThread, NULL, NULL, NULL);
WaitForSingleObject(hThreads,INFINITE);
printf("exit\n");
CloseHandle(hThreads);
}
- SOCKET编程进阶之Overlapped IO完成例程模型
- SOCKET编程进阶之Overlapped IO完成例程模型
- SOCKET编程进阶之Overlapped I/O完成例程模型
- SOCKET编程进阶之Overlapped I/O完成例程模型
- 【网络编程】之十一、重叠IO Overlapped IO 完成例程
- 【网络编程】之十一、重叠IO Overlapped IO 完成例程
- SOCKET编程进阶之Overlapped I/O事件通知模型
- SOCKET编程进阶之Overlapped I\O事件通知模型
- SOCKET编程进阶之Overlapped I\O事件通知模型
- socket通信之七:Overlapped I/O 完成例程模型实现的客户/服务器模型
- Socket I/O模型之重叠I/O(overlapped I/O)--完成例程方式
- Socket编程模型之重叠IO(Overlapped I/O)模型
- Overlapped I/O模型--完成例程
- Overlapped I/O模型--完成例程
- 网络编程五种IO模型之重叠IO模型-完成例程
- 重叠IO模型之完成例程示例
- Winsock 网络编程 Socket模型之Overlapped模型
- Winsock IO模型之Overlapped模型
- 这种软件设计原则你未必懂
- SuSELINUX SSHD登陆问题
- js注册表2
- 收藏--这一年~
- js注册表3
- SOCKET编程进阶之Overlapped IO完成例程模型
- 时间段操作!
- ListView应用
- 如何破解软件狗,dongle
- Struts 2 + Spring 集成
- debian Squeeze配置apache php mysql环境,debian中apache目录结构
- nand flash坏块管理OOB,BBT,ECC
- VC++6 实现界面使用XP风格
- ckeditor的详细配置