Winsock 网络编程 Socket模型之WSAEventSelect模型
来源:互联网 发布:淘宝电商线下实体店 编辑:程序博客网 时间:2024/04/19 11:34
创建监听用Socket
// 载入socket DLL
WSADATA wdata;
if (WSAStartup(MAKEWORD(2, 2), &wdata) != 0) {
// 失败
}
// 创建监听m_ListenSocket
m_ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == m_ListenSocket) {
// 失败
}
// 启动受信线程
m_ThreadId = 0;
m_Thread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)ReceiveThread, NULL, 0, &m_ThreadId );
受信线程
void ReceiveThread()
{
//**************************************************
// 创建Event对象
//**************************************************
// 处理结果
BOOL bResult = TRUE;
// Event对象数
DWORD eventTotal = 0;
// Event对象数组
WSAEVENT eventArray[WSA_MAXIMUM_WAIT_EVENTS];
// socket数组
SOCKET socketArray[WSA_MAXIMUM_WAIT_EVENTS];
// 把监听socket放入socket数组的首位置
socketArray[eventTotal] = m_ListenSocket;
// 创建监听socket用的Event对象、放入Event对象数组的首位置
if ((eventArray[eventTotal] = ::WSACreateEvent()) == WSA_INVALID_EVENT) {
// 失败
bResult = FALSE;
}
if (bResult) {
// 监听用event对象和监听socket绑定:绑定接受,关闭事件
if (SOCKET_ERROR == ::WSAEventSelect(m_ListenSocket,
eventArray[eventTotal],
FD_ACCEPT|FD_CLOSE) ) {
// 失败
bResult = FALSE;
} else {
// Event对象数+1
eventTotal++;
}
}
//**************************************************
// 监听socket绑定
//**************************************************
if (bResult) {
// 绑定
sockaddr_in ser_addr;
ser_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
ser_addr.sin_family=AF_INET;
ser_addr.sin_port=htons(50000);
if (SOCKET_ERROR == bind(m_ListenSocket, (LPSOCKADDR)&ser_addr, sizeof(ser_addr))) {
// 失败
bResult = FALSE;
}
}
if (bResult) {
// 监听开始
if (SOCKET_ERROR == listen(m_ListenSocket, 5)) {
// 失败
bResult = FALSE;
}
}
//**************************************************
// 等待和处理网络事件
//**************************************************
if (bResult) {
DWORD signaledIndex = 0;
SOCKET signaledSocket = INVALID_SOCKET;
WSAEVENT signaledEvent = WSA_INVALID_EVENT;
//**************************************************
// 等待网络事件
//**************************************************
while(TRUE) {
//等待event对象被激发
signaledIndex = ::WSAWaitForMultipleEvents(eventTotal,
eventArray,
FALSE,
INFINITE,
FALSE);
if (WSA_WAIT_FAILED == signaledIndex) {
// 失败
break;
}
// 根据被激发的event对象的索引值,取得对应的socket以及event对象
signaledSocket = socketArray[signaledIndex - WSA_WAIT_EVENT_0];
signaledEvent = eventArray[signaledIndex - WSA_WAIT_EVENT_0];
// 枚举网络中、在被激活的socket上、发生的网络事件
WSANETWORKEVENTS netEvents;
if (SOCKET_ERROR == ::WSAEnumNetworkEvents(signaledSocket, signaledEvent, &netEvents)){
// 失败
break;
}
//******************************************************
// FD_ACCEPT事件:网络中有客户端的连接请求
//******************************************************
if (netEvents.lNetworkEvents & FD_ACCEPT) {
// 网络错误
if (netEvents.iErrorCode[FD_ACCEPT_BIT] != 0) {
// 失败
break;
}
sockaddr_in cli_addr;
int addrlen = sizeof(cli_addr);
// 连接
if ((m_ClientSocket1 = accept(signaledSocket, (sockaddr *)&cli_addr, &addrlen))
== INVALID_SOCKET) {
// 失败
break;
}
// accept函数执行后,也会激活监听用socket的event对象,重置监听用socket的event对象
WSAResetEvent(signaledEvent);
// 判断是否超过最大可管理的socket数64
if (eventTotal > WSA_MAXIMUM_WAIT_EVENTS) {
// 如果超过64个,关闭该连接,不再接收连接要求
closesocket(m_ClientSocket1);
break;
}
// 把通信用socket放入socket数组
socketArray[eventTotal] = m_ClientSocket1;
// 为该通信用socket,创建event对象,并放入event对象管理数组
if ((eventArray[eventTotal] = ::WSACreateEvent()) == WSA_INVALID_EVENT) {
// 失败
// 关闭该连接
closesocket(socketArray[eventTotal]);
break;
}
// event对象邦定:绑定读取,关闭事件
if (SOCKET_ERROR == ::WSAEventSelect(socketArray[eventTotal],
eventArray[eventTotal],
FD_READ|FD_CLOSE) ) {
// 失败
// 关闭连接和event对象
closesocket(socketArray[eventTotal]);
WSACloseEvent(eventArray[eventTotal]);
break;
}
// Event对象数+1
eventTotal++;
}
//**************************************************
// FD_READ事件:网络中有可读入数据
//**************************************************
if (netEvents.lNetworkEvents & FD_READ) {
// 网络错误
if (netEvents.iErrorCode[FD_READ_BIT] != 0) {
// 失败
break;
}
char recved[50];
ZeroMemory(recved, 50);
int recvedLen = 50;
char info[50];
ZeroMemory(info, 50);
// 接收数据
recvedLen = recv(signaledSocket, recved, recvedLen, 0);
if (recvedLen == SOCKET_ERROR || recvedLen == 0) {
// 失败
break;
}
}
//**************************************************
// FD_CLOSE事件:断开连接
//**************************************************
if (netEvents.lNetworkEvents & FD_CLOSE) {
// 网络错误
if (netEvents.iErrorCode[FD_CLOSE_BIT] != 0) {
// 失败
break;
}
// 关闭连接
closesocket(signaledSocket);
WSACloseEvent(signaledEvent);
// 把socket和event对象从管理数组中删除
for (DWORD i = signaledIndex - WSA_WAIT_EVENT_0; i < eventTotal - 1; i++) {
socketArray[i] = socketArray[i + 1];
eventArray[i] = eventArray[i + 1];
}
// Event对象数-1
eventTotal--;
}
}
}
}
- Winsock 网络编程 Socket模型之WSAEventSelect模型
- SOCKET编程之WSAEventSelect模型
- Winsock 网络编程 Socket模型之Select模型
- Winsock 网络编程 Socket模型之WSAAsyncSelect模型
- Winsock 网络编程 Socket模型之Overlapped模型
- Winsock 网络编程 Socket模型之Completion模型
- Winsock IO模型之WSAEventSelect模型
- Winsock WSAEventSelect模型范例
- winsock IO模型 WSAEventSelect
- 网络编程五种IO模型之WSAEventSelect模型
- Winsock异步模型之二(WSAEventSelect)
- Winsock异步模型之二(WSAEventSelect)
- Windows socket之WSAEventSelect模型
- Windows socket之WSAEventSelect模型
- Windows socket之WSAEventSelect模型
- Windows socket之WSAEventSelect模型
- socket网络编程之路 第四篇 ------winsock网络编程模型(1)之概述
- WinSock WSAEventSelect 服务端模型 (多线程)
- 配置notes.ini参数调整domino JVM虚拟机内存大小
- 判断临时表是否存在(临时表的删除)
- asp.net MVC + linq to Entity简单教程(二)MVC的简单操作
- error MSB4006 错误解决
- 使用定时器实现弹弹球
- Winsock 网络编程 Socket模型之WSAEventSelect模型
- 从 2.4 到 2.6:Linux 内核可装载模块机制的改变对设备驱动的影响(转)
- HTML格式
- sysfs: cannot create duplicate filename '/devices/virtual/misc/leds'问题处理
- Linux 中的零拷贝技术,第 1 部分
- MPEG-4标签格式翻译
- vim插件之ctags
- MDK 编译文件大小说明(Program Size)
- Spring学习笔记