Socket重叠IO

1.为什么到现在才弄懂这个

不知道这个Socket重叠IO这种模型是不是socket IO完成端口的基础,不过我感觉,学习一下这个再去学习socket IO完成端口是比较有好处的。

这个Scoket重叠IO我以前记得看过好几次,都没看懂。一部分原因是我没能静态心来写代码,还有更重要的原因就是,Socket重叠他们的结构体参数,还有传参数让人很难理解。下面我将对这些数据结构和参数进行一下讲解

2.初识WSARecv 函数

int WSARecv(
        SOCKET s,//要接收消息的socket
        LPWSABUF lpBuffers, //一个结构体数组。当接收IO操作完毕后接收内容就在这个里面了
        DWORD dwBufferCount, //要接多少个WSABUF
        LPDWORD lpNumberOfBytesRecvd,//接收了多少个字节
        LPDWORD lpFlags,
        LPWSAOVERLAPPED lpOverlapped,//Overlapped结构体指针
        LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine//在本节用不用
        );

lpBuffers参数:这是一WSABUF数组,意思是这个函数可以接收不止一个字符缓冲,但是我们一般用一个就够了。 接收多个我还没能测试

dwBufferCount参数:是指上一个参数的数组个数

lpOverlapped参数:这个参数是Overlappad结构体指针,这个指针当IO操作完毕的时候,这里会被系统填充。当IO操作完成时这个结构也可以通过WSAGetOverlappedResult得到

返回值:

0:没有错误发生,IO操作当即完成

SOCKET_ERROR:发生错误

如果是SOCKET_ERROR并且WSAGetLastError() == WSA_IO_PENDING 这时表示操作已经提交。异步操作大部分都是这样的。

3.何时得到收取的消息,然后取出消息

当异常操作完成时,Overlapped的hEvent这个事件会触发。这时Overlapped的InternalHigh表示接受的字节数。Internal表示错误代码。消息的内容即是你当初调用WSARecv时传入的lpBuffers参数。

4.代码组织

以服务端为例

首先传入WSARecv的几个参数必定与一个socket关联。而且这些参数在异步调用完成之后,但是以后还要用(在WaitForMutiObjects时要用到),而且每一个socket得拥有一个不同的Event来标识是哪个客户端来消息了。所以为每一个客户端socket构造一个Overlapped结构。比如我测试的代码中每一个客户端都有这样一个结构体,而且当accept来的时候表示有新的socket连接,就得生成这样一个结构体,当客户端掉线的时候,就得删除这样一个结构体

下面就是这个结构体:

struct CClientInfo
{
public:
    CClientInfo()
    {
        ZeroMemory(&m_ol,sizeof(m_ol));
        ZeroMemory(m_szBuf,256);
        m_ol.hEvent = WSACreateEvent();
    }
    ~CClientInfo()
    {
        WSACloseEvent(m_ol.hEvent);
    }
    WSAOVERLAPPED m_ol;
    SOCKET sSocket;
    CString strIp;
    u_short nPort;
    CString GetShowText();
    char m_szBuf[256];
};

下面是两个函数,一个是当客户端连接的时候,一个是当客户端断开的时候

CClientInfo * CServerDlg::OnSocketConnected(SOCKET sClientSocket,sockaddr_in * saClient)
{
    u_short uPort =  ntohs(((sockaddr_in *)saClient)->sin_port);
    CString strIp = CA2T(inet_ntoa(((sockaddr_in *)saClient)->sin_addr));
    CClientInfo * pClientInfo = new CClientInfo;
    pClientInfo->nPort = uPort;
    pClientInfo->strIp = strIp;
    pClientInfo->sSocket = sClientSocket;
    LockClientArray();
    m_ClientArray.Add(pClientInfo);
    int nIndexInserted = m_ClientListBox.AddString(pClientInfo->GetShowText());
    m_ClientListBox.SetItemData(nIndexInserted,pClientInfo->sSocket);
    UnLockClientArray();
    return pClientInfo;
}

void CServerDlg::OnSocketDisconnect(SOCKET aClientSocket)
{
    LockClientArray();
    for(int i = 0;i<m_ClientArray.GetCount();i++)
    {
        CClientInfo * pClientInfo = m_ClientArray.GetAt(i);
        if(pClientInfo->sSocket == aClientSocket)
        {
            m_ClientListBox.DeleteString(m_ClientListBox.FindString(0,pClientInfo->GetShowText()));
            delete pClientInfo;
            m_ClientArray.RemoveAt(i);
            break;
        }
    }
    UnLockClientArray();
}

5.没有测试的内容和疑问

如果WSARecv调用两次会是什么情况,有没有影响。

我没有用异步AcceptEx,感觉这个函数异步了,作用也不大,以后如果需要的话,再学习吧

发送的时候没有用WSASend,以后再学习

时间: 2024-08-05 19:32:20

Socket重叠IO的相关文章

重叠IO 模型

1. 重叠模型的优点 2. 重叠模型的基本原理 3. 关于重叠模型的基础知识 4. 重叠模型的实现步骤 5. 多客户端情况的注意事项 一.重叠模型的优点   1.可以运行在支持Winsock2的所有Windows平台 ,而不像完成端口只是支持NT系统. 2.比起阻塞.select.WSAAsyncSelect以及WSAEventSelect等模型,重叠I/O(Overlapped   I/O)模型使应用程序能达到更佳的系统性能.    因为它和这4种模型不同的是,使用重叠模型的应用程序通知缓冲区

重叠IO

// 重叠IO网络模式.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<WinSock2.h> #include<windows.h> #include<iostream> using namespace std; #pragma comment (lib,"ws2_32.lib") #define PORT 6000 #define MSGSIZE 1024 typede

重叠io操作

第一章 一. 重叠模型的优点 1. 可以运行在支持Winsock2的所有Windows平台 ,而不像完成端口只是支持NT系统. 2. 比起阻塞.select.WSAAsyncSelect以及WSAEventSelect等模型,重叠I/O(Overlapped I/O)模型使应用程序能达到更佳的系统性能. 因为它和这4种模型不同的是,使用重叠模型的应用程序通知缓冲区收发系统直接使用数据,也就是说,如果应用程序投递了一个10KB大小的缓冲区来接收数据,且数据已经到达套接字,则该数据将直接被拷贝到投递

四.Windows I/O模型之重叠IO(overlapped)模型

1.适用于除Windows CE之外的各种Windows平台.在使用这个模型之前应该确保该系统安装了Winsock2.重叠模型的基本设计原理是使用一个重叠的数据结构,一次投递一个或多个Winsock I/O请求.在重叠模型中,收发数据使用WSA开头的函数. 2.WSA_FLAG_OVERLAPPED标志:要使用重叠模型.在创建套接字的时候,必须加上该标志.SOCKET s=WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);假如

windows的重叠IO模型

2019年5月29日 11:58 ? ? 同一线程内部向多个目标传输(或冲多个目标接收)数据引起的IO重叠现象称为"重叠IO".为了完成这项任务,调用IO的函数应立即返回,只有这样才能返送后续数据. 重叠IO收发数据最重要的前提条件就是异步IO. 在windows中重叠IO的重点并非IO本身,而是如何确认IO完成时的状态.因为不管输入还是输出,只要时非阻塞模式的,就要另外确认执行结果.确认执行结果前需要经过特殊的处理过程. ? ? 创建重叠IO套接字 #include <wins

socket之IO多路复用

IO 多路复用 I/O多路复用指:通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作. Linux Linux中的 select,poll,epoll 都是IO多路复用的机制. select select最早于1983年出现在4.2BSD中,它通过一个select()系统调用来监视多个文件描述符的数组,当select()返回后,该数组中就绪的文件描述符便会被内核修改标志位,使得进程可以获得这些文件描述符从而进行后续的读写操作. sele

PHP实现系统编程(一) --- 网络Socket及IO多路复用【网摘】

一直以来,PHP很少用于socket编程,毕竟是一门脚本语言,效率会成为很大的瓶颈,但是不能说PHP就无法用于socket编程,也不能说PHP的socket编程性能就有多么的低,例如知名的一款PHP socket框架 workerman 就是用纯PHP开发,并且号称拥有优秀的性能,所以在某些环境下,PHP socket编程或许也可一展身手. PHP提供了一系列类似C语言socket库中的方法供我们调用: [php] view plain copy socket_accept - Accepts 

java 大文件上传 断点续传 完整版实例 (Socket、IO流)

原文出自:https://blog.csdn.net/seesun2012 java两台服务器之间,大文件上传(续传),采用了Socket通信机制以及JavaIO流两个技术点,具体思路如下: 实现思路: 1.服:利用ServerSocket搭建服务器,开启相应端口,进行长连接操作 2.服:使用ServerSocket.accept()方法进行阻塞,接收客户端请求 3.服:每接收到一个Socket就建立一个新的线程来处理它 4.客:利用Socket进行远程连接,询问已上传进度 5.客:使用File

TCP编程:select提高服务器处理能力 [socket多路IO复用]

服务器: #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <strings.h> #include <sys/wait.h>