如何产生ioexception_生活中需要配合的例子

如何产生ioexception_生活中需要配合的例子
这是在学《Windows网络编程(第二版)》第六章时制作的一个例子
由于书中没有给出简洁的例子,本人在学这里时就费了很多时间。
现在把完成的代码贴出来,供大家参考。
下面包括了主程序部分,工作线程在(2)中贴出,由于代码太长。
本程序在VS2003编译器编译运行。在6.0下可能需要稍加修改。
#include
#include
#include

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

这是在学《Windows网络编程(第二版)》第六章时制作的一个例子
由于书中没有给出简洁的例子,本人在学这里时就费了很多时间。
现在把完成的代码贴出来,供大家参考。
下面包括了主程序部分,工作线程在(2)中贴出,由于代码太长。
本程序在VS2003编译器编译运行。在6.0下可能需要稍加修改。

#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <mswsock.h>    //微软扩展的类库

using namespace std;
#define SEND 0
#define RECV 1
#define ACCEPT 2

#define DATA_LENGTH 1000
//单句柄数据定义
typedef struct _PER_HANDLE_DATA
{

    SOCKET socket;    //相关的套接字
    SOCKADDR_STORAGE clientAddr;    //客户端的地址
}PER_HANDLE_DATA,*LPPER_HANDLE_DATA;

//但IO操作数据
typedef struct{

    OVERLAPPED overlapped;
    WSABUF buffer;    //一个数据缓冲区,用于WSASend/WSARecv中的第二个参数
    char dataBuffer[DATA_LENGTH];    //实际的数据缓冲区
    int dataLength;                    //实际的数据缓冲区长度
    int operatorType;                //操作类型,可以为SEND/RECV两种
    SOCKET client;                    //分别表示发送的字节数和接收的字节数
}PER_IO_DATA,*LPPER_IO_DATA;

void main()
{

    HANDLE CompletionPort;
    WSADATA data;
    SYSTEM_INFO info;
    SOCKADDR_IN addr;
    SOCKET Listen;

    unsigned int i;
    WSAStartup(MAKEWORD(2,2),&data);

    //创建一个IO完成端口
    CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
    //确定处理器的数量
    GetSystemInfo(&info);    //创建线城
    for(i=0;i<info.dwNumberOfProcessors * 2;i++)
    {

        //根据处理器的数量创建相应多的处理线程
        HANDLE thread = CreateThread(NULL,0,ServerThread,CompletionPort,0,NULL);
        CloseHandle(thread);
    }
    //创建一个监听套接字(进行重叠操作)
    Listen = WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
    //将监听套接字与完成端口绑定
    LPPER_HANDLE_DATA perDandleData;
    perDandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA));
    perDandleData->socket = Listen;
    CreateIoCompletionPort((HANDLE)Listen,CompletionPort,(ULONG_PTR)perDandleData,0);

    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port = htons(5500);

    bind(Listen,(PSOCKADDR)&addr,sizeof(addr));
    listen(Listen,5);

    LPFN_ACCEPTEX lpfnAcceptEx = NULL;    //AcceptEx函数指针
    //Accept function GUID
    GUID guidAcceptEx = WSAID_ACCEPTEX;
    //get acceptex function pointer
    DWORD dwBytes = 0;
    if(WSAIoctl(Listen,SIO_GET_EXTENSION_FUNCTION_POINTER,
        &guidAcceptEx,sizeof(guidAcceptEx),&lpfnAcceptEx,sizeof(lpfnAcceptEx),
        &dwBytes,NULL,NULL)==0)
        cout<<“WSAIoctl success…”<<endl;
    else{

        cout<<“WSAIoctl failed…”<<endl;
        switch(WSAGetLastError())
        {

        case WSAENETDOWN:
            cout<<“”<<endl;
            break;
        case WSAEFAULT:
            cout<<“WSAEFAULT”<<endl;
            break;
        case WSAEINVAL:
            cout<<“WSAEINVAL”<<endl;
            break;
        case WSAEINPROGRESS:
            cout<<“WSAEINPROGRESS”<<endl;
            break;
        case WSAENOTSOCK:
            cout<<“WSAENOTSOCK”<<endl;
            break;
        case WSAEOPNOTSUPP:
            cout<<“WSAEOPNOTSUPP”<<endl;
            break;
        case WSA_IO_PENDING:
            cout<<“WSA_IO_PENDING”<<endl;
            break;
        case WSAEWOULDBLOCK:
            cout<<“WSAEWOULDBLOCK”<<endl;
            break;
        case WSAENOPROTOOPT:
            cout<<“WSAENOPROTOOPT”<<endl;
            break;
        }
        return;
    }

    //while(true)
    //{

        //准备调用 AcceptEx 函数,该函数使用重叠结构并于完成端口连接
        LPPER_IO_DATA perIoData = (LPPER_IO_DATA)GlobalAlloc(GPTR,sizeof(PER_IO_DATA));
        memset(&(perIoData->overlapped),0,sizeof(OVERLAPPED));   
        perIoData->operatorType = ACCEPT;
        //在使用AcceptEx前需要事先重建一个套接字用于其第二个参数。这样目的是节省时间
        //通常可以创建一个套接字库
        perIoData->client = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,0,0,WSA_FLAG_OVERLAPPED);

        perIoData->dataLength = DATA_LENGTH;
        DWORD flags = 0;
       
        //调用AcceptEx函数,地址长度需要在原有的上面加上16个字节
        //注意这里使用了重叠模型,该函数的完成将在与完成端口关联的工作线程中处理
        cout<<“Process AcceptEx function wait for client connect…”<<endl;
        int rc = lpfnAcceptEx(Listen,perIoData->client,perIoData->dataBuffer,
            perIoData->dataLength-((sizeof(SOCKADDR_IN)+16)*2),
            sizeof(SOCKADDR_IN)+16,sizeof(SOCKADDR_IN)+16,&dwBytes,
            &(perIoData->overlapped));
        if(rc == FALSE)
        {

            if(WSAGetLastError()!=ERROR_IO_PENDING)
                cout<<“lpfnAcceptEx failed..”<<endl;
        }

        cin>>i;
    closesocket(Listen);
    WSACleanup();
}

DWORD WINAPI ServerThread(LPVOID lpParam)
{

    HANDLE CompletionPort = (HANDLE)lpParam;
    DWORD bytes;
    LPPER_HANDLE_DATA perHandleData = NULL;    //单句柄数据
    LPPER_IO_DATA perIoData;            //单IO数据
    DWORD Flags;
    int ret;
    DWORD RecvBytes;
    //进入循环的等待重叠操作的完成
    while(true)
    {

        bytes = -1;
        ret=GetQueuedCompletionStatus(
            CompletionPort,                //原先的完成端口句柄
            &bytes,                        //重叠操作完成的字节数
            (LPDWORD)&perHandleData,    //原先和完成端口句柄关联起来的单句柄数据
            (LPOVERLAPPED*)&perIoData,    //用于接收已完成的IO操作的重叠结构
            INFINITE);                    //在完成端口上等待的时间 INFINITE 为无限等待
       
        //先检查在套接字上是否发生错误
        //当发生错误时关闭套接字同时释放掉所有的内存.
        int i = 0;
        if(bytes == 0 && (perIoData->operatorType == RECV ||
            perIoData->operatorType == SEND))
        {

            closesocket(perHandleData->socket);
            GlobalFree(perHandleData);
            GlobalFree(perIoData);
            cout<<“closesocket and globalfree perhandledata periodata!”<<endl;
            continue;
        }
        //这是AcceptEx函数处理完成,在下面处理
        if(perIoData->operatorType == ACCEPT)    //处理连接操作
        {

            //使用GetAcceptExSockaddrs函数 获得具体的各个地址参数.
            if(setsockopt( perIoData->client, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, 
                ( char* )&(perHandleData->socket ), sizeof( perHandleData->socket ) )==SOCKET_ERROR)
                cout<<“setsockopt…”<<endl;

            perHandleData->socket = perIoData->client;

            //memcpy(&(perHandleData->clientAddr),raddr,sizeof(raddr));
            //将新的客户套接字与完成端口连接
            CreateIoCompletionPort((HANDLE)perHandleData->socket,
                CompletionPort,(ULONG_PTR)perHandleData,0);

            memset(&(perIoData->overlapped),0,sizeof(OVERLAPPED));
            perIoData->operatorType = RECV;        //将状态设置成接收
            //设置WSABUF结构
            perIoData->buffer.buf = perIoData->dataBuffer;
            perIoData->buffer.len = perIoData->dataLength = DATA_LENGTH;

            cout<<“wait for data arrive(Accept)…”<<endl;
            Flags = 0;
            if(WSARecv(perHandleData->socket,&(perIoData->buffer),1,
                &RecvBytes,&Flags,&(perIoData->overlapped),NULL)==SOCKET_ERROR)
                if(WSAGetLastError()==WSA_IO_PENDING)
                    cout<<“WSARecv Pending…”<<endl;
            continue;           
        }
        if(perIoData->operatorType == RECV)
            cout<<perIoData->buffer.buf<<endl;    //将接收到的数据显示出来
        Flags = 0;
        perIoData->operatorType = RECV;            //设置成接受数据类型

        ZeroMemory(&(perIoData->overlapped),sizeof(OVERLAPPED));
        //重新投递一个新的接收请求
        cout<<” wait for data arrive…”<<endl;
        WSARecv(perHandleData->socket,&(perIoData->buffer),1,
            &RecvBytes,&Flags,&(perIoData->overlapped),NULL);
    }

    return 0;
}

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/kener_linfeng/archive/2009/05/03/4145471.aspx

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/188173.html原文链接:https://javaforall.net

(0)
上一篇 2026年4月17日 下午1:16
下一篇 2026年4月17日 下午1:22


相关推荐

  • Coze智能体实战:零基础学会搭建热点监控AI Agent,选题效率提升10倍

    Coze智能体实战:零基础学会搭建热点监控AI Agent,选题效率提升10倍

    2026年3月13日
    2
  • MATLAB矩阵复制及扩充

    MATLAB矩阵复制及扩充文章目录一、repmat()方法二、Kron()方法一、repmat()方法例一:(行方向和列方向分别平铺矩阵,红框2,3表示平铺倍数)TIPS:【原矩阵】处可用用户自定义的矩阵变量代替   即Mat=[123;456],可用Mat替代function中原矩阵的位置例二:(行方向和列方向分别平铺矩阵,红框2,3表示平铺倍数)例三:(列方向平铺矩阵,红框2表示平铺矩阵的倍数)例四:(行方向平铺矩阵,红框3表示平铺矩阵的倍数)二、Kron()方法kron(A,B)

    2022年6月25日
    171
  • 迭代阈值法

    迭代阈值法通过迭代方法选择阈值 计算方法如下 1 选择灰度图的平均值作为初始阈值 T0 2 计算小于等于 T0 的平均值 T1 和大于 T0 的平均值 T2 3 新的阈值为 T T1 T2 2 4 比较 T 和 T0 若相等 则返回 T 即为迭代阈值 否则 T0 T 重复 1 3

    2026年3月26日
    2
  • NeHe OpenGL第三十三课:TGA文件[通俗易懂]

    NeHeOpenGL第三十三课:TGA文件加载压缩和未压缩的TGA文件:在这一课里,你将学会如何加载压缩和为压缩的TGA文件,由于它使用RLE压缩,所以非常的简单,你能很快地熟悉它的。 我见过很多人在游戏开发论坛或其它地方询问关于TGA读取的问题。接下来的程序及注释将会向你展示如何读取未压缩的TGA文件和RLE压缩的文件。这个详细的教程适合于OpenGL,但是我计划改进它…

    2022年4月16日
    50
  • php navigator,navigator对象

    php navigator,navigator对象navigator对象appName:浏览器软件名称,主要用来判断客户使用的是什么核心的浏览器。如果是IE浏览器的话,返回值为:MicrosoftInternetExplorer如果是Firefox浏览器的话,返回值为:NetscapeappVersion:浏览器软件的核心版本号。systemLanguage:系统语言userLanguage:用户语言platform:平台HTML>ph…

    2025年10月29日
    3
  • VS开发中遇到无法解析外部符号问题(LNK错误)

    VS开发中遇到无法解析外部符号问题(LNK错误)在VS开发中,很容易遇到外部符号无法解析的问题,而这些问题大部分都是引用库失败导致的,只需正确的加载到了库,这类问题就可以解决了但也存在非库的原因,比如编码问题关于VS编码格式以及VS修改行尾编码格式问题如图解决办法代码文件保存行尾不一致导致的,行尾改为Windows(CRLF)。修改后即可编译通过…

    2022年6月28日
    68

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号