WSAevent

    // TODO: 在此添加控件通知处理程序代码
    CString str,edit_str;
    GetDlgItemText(IDC_StartServer, str);
            // 事件句柄和套节字句柄表
    WSAEVENT    eventArray[WSA_MAXIMUM_WAIT_EVENTS];
    SOCKET      sockArray[WSA_MAXIMUM_WAIT_EVENTS];
    int nEventTotal = 0;
    if (str=="开始")
    {
        SetDlgItemText(IDC_StartServer,_T("停止"));

    // 创建监听套节字
    /* Enable address reuse */
    int ret;
    char on;
    on = 1;
    USHORT nPort = 4567;    // 此服务器监听的端口号
    SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    ret = setsockopt( sListen, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) );
    sockaddr_in sin;
    memset( &sin, 0, sizeof(sin) );
    sin.sin_family = AF_INET;
    sin.sin_port = htons(nPort);
    sin.sin_addr.S_un.S_addr = INADDR_ANY;  

    if(::bind(sListen, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR)
    {
        edit_str= " Failed bind()";
    //    ::AfxMessageBox(_T("Failed bind"));
        GetDlgItem(IDC_EDIT3)->SetWindowText(edit_str);    

    }
    else
    {
        //::AfxMessageBox(_T("bind success"));
        GetDlgItem(IDC_EDIT3)->SetWindowText(_T("bind success!"));
    }
    ::listen(sListen, 5);  

    // 创建事件对象,并关联到新的套节字
    WSAEVENT event = ::WSACreateEvent();
    ::WSAEventSelect(sListen, event, FD_ACCEPT|FD_CLOSE);
    // 添加到表中
    eventArray[nEventTotal] = event;
    sockArray[nEventTotal] = sListen;
    nEventTotal++;  

    // 处理网络事件
    while(TRUE)
    {
        // 在所有事件对象上等待
        int nIndex = ::WSAWaitForMultipleEvents(nEventTotal, eventArray, FALSE, WSA_INFINITE, FALSE);
        // 对每个事件调用WSAWaitForMultipleEvents函数,以便确定它的状态
        nIndex = nIndex - WSA_WAIT_EVENT_0;//发生的事件对象的索引,一般是句柄数组中最前面的那一个,然后再用循环依次处理后面的事件对象
        for(int i=nIndex; i<nEventTotal; i++)
        {
            int ret;
            ret = ::WSAWaitForMultipleEvents(1, &eventArray[i], TRUE, 1000, FALSE);
            if(ret == WSA_WAIT_FAILED || ret == WSA_WAIT_TIMEOUT)
            {
                continue;
            }
            else
            {
                // 获取到来的通知消息,WSAEnumNetworkEvents函数会自动重置受信事件
                WSANETWORKEVENTS event;
                ::WSAEnumNetworkEvents(sockArray[i], eventArray[i], &event);
                if(event.lNetworkEvents & FD_ACCEPT)                // 处理FD_ACCEPT通知消息
                {
                    if(event.iErrorCode[FD_ACCEPT_BIT] == 0)
                    {
                        if(nEventTotal > WSA_MAXIMUM_WAIT_EVENTS)
                        {
                            GetDlgItem(IDC_EDIT1)->SetWindowText(_T(" Too many connections!"));
                           // printf(" Too many connections! /n");
                            continue;
                        }
                        SOCKET sNew = ::accept(sockArray[i], NULL, NULL);
                        WSAEVENT event = ::WSACreateEvent();
                        ::WSAEventSelect(sNew, event, FD_READ|FD_CLOSE|FD_WRITE);
                        // 添加到表中
                        eventArray[nEventTotal] = event;
                        sockArray[nEventTotal] = sNew;
                        nEventTotal++;
                    }
                }
                else if(event.lNetworkEvents & FD_READ)         // 处理FD_READ通知消息
                {
                    if(event.iErrorCode[FD_READ_BIT] == 0)
                    {
                        char szText[1024];
                        int nRecv = ::recv(sockArray[i], szText, strlen(szText), 0);
                        if(nRecv > 0)
                        {  

                            MessageBox(LPCTSTR(szText));
                        szText[nRecv] = ‘\0‘;
                        }
                    }
                }
                else if(event.lNetworkEvents & FD_CLOSE)        // 处理FD_CLOSE通知消息
                {
                    if(event.iErrorCode[FD_CLOSE_BIT] == 0)
                    {
                        ::closesocket(sockArray[i]);
                        for(int j=i; j<nEventTotal-1; j++)
                        {
                            sockArray[j] = sockArray[j+1];
                            sockArray[j] = sockArray[j+1];
                        }
                        nEventTotal--;
                    }
                }
                else if(event.lNetworkEvents & FD_WRITE)        // 处理FD_WRITE通知消息
                {
                }
            }
        }
    }
    }
    else
    {

        SetDlgItemText(IDC_StartServer,_T("开始"));
    }

时间: 2024-10-12 16:05:05

WSAevent的相关文章

Windows IO方法

一.综述 Winsock分别提供了"套接字模式"和"套接字I / O模型",可对一个套接字上的I/O行为加以控制.其中,套接字模式用于决定在随一个套接字调用时,那些Winsock函数的行为.而另一方面,套接字模型描述了一个应用程序如何对套接字上进行的I/O进行管理及处理. Winsock提供了两种套接字模式:锁定和非锁定. Winsock提供五中套接字模型:这些模型包括select(选择).WSAAsyncSelect(异步选择).WSAEventSelect(事件

基于Delphi的Socket I/O模型全接触 good

老陈有一个在外地工作的女儿,不能经常回来,老陈和她通过信件联系.他们的信会被邮递员投递到他们的信箱里. 这和Socket模型非常类似.下面我就以老陈接收信件为例讲解Socket I/O模型. 一:select模型 老陈非常想看到女儿的信.以至于他每隔10分钟就下楼检查信箱,看是否有女儿的信,在这种情况下,“下楼检查信箱”然后回到楼上耽误了老陈太多的时间,以至于老陈无法做其他工作. select模型和老陈的这种情况非常相似:周而复始地去检查......如果有数据......接收/发送.......

Windows Socket五种I/O模型——代码全攻略(转)

Winsock 的I/O操作: 1. 两种I/O模式 阻塞模式:执行I/O操作完成前会一直进行等待,不会将控制权交给程序.套接字 默认为阻塞模式.可以通过多线程技术进行处理. 非阻塞模式:执行I/O操作时,Winsock函数会返回并交出控制权.这种模式使用 起来比较复杂,因为函数在没有运行完成就进行返回,会不断地返回 WSAEWOULDBLOCK错误.但功能强大.为了解决这个问题,提出了进行I/O操作的一些I/O模型,下面介绍最常见的三种: Windows Socket五种I/O模型——代码全攻

IOCP扩展方法AcceptEx, DisconnectEx, GetAcceptExSockaddr用法示例

这篇文章记录了我刚接触IOCP模型时的理解,对于初学者,应该算不错的调试程序,仅有一个400多行代码的dpr文件,可以直接用WriteLn输出信息,前提是会用delphi建立Console Application,当然你也可以很容易的就改成了C控制台程序或是其它语言.附加代码中有详细的注释,如果你已有IOCP经验,那么请不用在此浪费时间,这个示例不适合你.示例仅展示了IOCP中AcceptEx, DisconnectEx, GetAcceptExSockaddr等的用法.在文章最后有推荐的两个连

Socket编程模式

Socket编程模式 本文主要分析了几种Socket编程的模式.主要包括基本的阻塞Socket.非阻塞Socket.I/O多路复用.其中,阻塞和非阻塞是相对于套接字来说的,而其他的模式本质上来说是基于Socket的并发模式.I/O多路复用又主要分析了分析linux和windows下的常用模型.最后,比较这几种Socket编程模式的优缺点,并讨论多线程与Socket的组合使用和服务器开发的常用模式. 阻塞模式 阻塞模式是最基本的Socket编程模式,在各种关于网络编程的书籍中都是入门的例子.就像其

套接字I/O模型-重叠I/O

重叠模型的基本设计原理是让应用程序使用重叠的数据结构,一次投递一个或多个WinsockI/O请求.针对那些提交的请求,在它们完成之后,应用程序可为它们提供服务.模型的总体设计以Windows重叠I/O机制为基础.这个机制可通过ReadFile和WriteFile两个函数,在设备上执行I/O操作. 要想在一个套接字上使用重叠I/O模型,首先必须创建一个设置了重叠标志的套接字. 主要有两种方法来管理重叠I/O的请求.1.事件对象通知 2.完成实例. 事件通知: 重叠I/O的事件通知方法要求将Wind

Winsock I/O 模型详解

Winsock共有五种类型的套接字I/O模型,可让Winsock应用程序对I/O进行管理,它们包括: select(选择).WSAAsyncSelect(异步选择).WSAEventSelect(事件选择).overlapped(重叠).以及completion port(完成端口). 1.Select(选择)模型 利用select函数,判断套接字上是否存在数据,或者能否向一个套接字写入数据.目的是防止应用程序在套接字处于锁定模式时,调用recv(或send)从没有数据的套接字上接收数据,被迫进

套接字I/O模型-WSAEventSelect(转载)

和WSAAsyncSelect类似,它也允许应用程序在一个或多个套接字上,接收以事件为基础的网络事件通知. 该模型最主要的区别是在于网络事件是由对象句柄完成的,而不是通过窗口例程完成. 事件通知 事件通知模型要求应用程序针对打算使用的每一个套接字,首先创建一个事件对象.创建方法是调用WSACreateEvent函数: WSAEVENT WSACreateEvent(void); WSACreateEvent的返回值很简单,就是一个人工重设的事件对象句柄,一旦得到了事件对象句柄之后,必须将它与某个

winsock编程WSAEventSelect模型

winsock编程WSAEventSelect模型 WSAEventSelect模型和WSAAsyncSelec模型类似,都是用调用WSAXXXXXSelec函数将socket和事件关联并注册到系统,并将socket设置成非阻塞模式.二者不同之处在于socket事件的通知方法:WSAAsyncSelec模型利用窗口句柄和消息映射函数通知网络事件,而WSAEventSelect模型利用WSAEVENT通知网络事件.完成WSAEventSelect模型需要涉及以下函数或结构: 1:WSAEventS