zoukankan      html  css  js  c++  java
  • windows平台通信基础

    ·概要:

         对于windows平台的通信模型一般分为两个:客户端使用MFC中的接口、服务器端使用IOCP通信模型。

    ·要点:

    基础:

        在windows中SOCKET是操作系统内部定义的数据结构。

        协议族在计算机中表示为一个整数—AF_INET,

                  Socket类型为SOCK_STREAM和SOCK_DGRAM。

        涉及到一些地址相关的类型;

            sockaddr:

                 作为函数参数而存在,在函数调用的时候需要类型转换;

            sockaddr_in:

                 需要配置的数据类型,定义为:

                    struct sockaddr_in{

                          short int sin_family;

                          unsigned short int sin_port;

                          struct in_addr sin_addr;

                          unsigned char sin_zero[8];

                    };

                  其中struct in_addr是另外定义的。

        相关头文件为:<winsock2.h>,同时需要连接动态库。

        初始化动态库:WSAStartup(MAKEWORD(2,2),&wsaData);

                      其中wsaData为WSADATA类型的变量。

        对应的库清理函数为WSACleanup()。

    Socket函数原型:SOCKET socket(int af,int type,int protocol);

             出错返回INVALID_SOCKET。

             常用法为:SOCKET s=socket(AF_INET,SOCK_STREAM,0);

    close socket函数:int closesocket(SOCKET s);

             成功返回0,否则返回SOCKET_ERROR。

    connect函数:int connect(SOCKET s,const struct sockaddr* name,

                                      int namelen);

              成功返回0,否则返回SOCKET_ERROR。

                         对于非阻塞模式为WSAEWOULDBLOCK表示错误。

    listen函数:int listen(SOCKET s,int backlog);

              成功返回0,否则返回SOCKET_ERROR。

    bind函数:int bind(SOCKET s,const struc sockaddr* name,

                            int namelen);

              成功返回0,否则返回SOCKET_ERROR。

    accept函数:SOCKET accept(SOCKET s,struct sockaddr* addr,

                                           int * addrlen);

              成功返回新连接的SOCKET,否则返回SOCKET_ERROR。

              其中addr和addrlen都是额外的返回值。

    send函数--阻塞函数:int send(SOCKET s,const cha* buf,int len,

                                          int flags);

              成功返回发送成功的字节数,否则返回SOCKET_ERROR。

    recv函数--阻塞函数:int recv(SOCKET s,char* buf,int len,int flags);

              成功返回接收的字节数,否则返回SOCKET_ERROR。

    常用地址设置:SOCKADDR_IN ServerAddr;

                      ServerAddr.sin_family=AF_INET;

                      ServerAddr.sin_port=htons(8888);

                      ServerAddr.sin_addr.s_addr=inet_addr("127.0.0.1");

                      或ServerAddr.sin_addr.s_addr=htonl(INADDR_ANY);

    IOCP通信模型:

    --基本原理:

        IOCP(I/O Completion Port--完成端口)内部采用的是前摄器模式。

        我理解的IOCP的工作过程是:

             首先需要一个接受新连接的循环:

                         接受新连接--将新连接绑定到IOCP--执行异步读数据

             然后是线程工作的循环:

                         检查完成的操作--判断完成操作的类型--执行分析判断操作

                            --执行异步循环

                     其中执行分析判断操作过程可能有异步写操作;

             在绑定socket和完成端口时就交由完成端口来记录socket;

             执行异步读取操作则可以保证socket不会丢失。

    --数据结构:

        重叠端口:是操作系统内部用来在IOCP内部交流的数据结构。

                     常用法是作为struct结构的首元素--做指针类型转换;

        传输数据缓存—WSABUF,用于系统将完成的数据缓存;

        同时需要保存关联的SOCKET和记录完成操作的数据的数目;

        这些概念说起来很抽象,不过看代码的话就很好理解了。

    --接口函数:

        主要有两个函数:

         1.HANDLE CreateIoCompletionPort(HANDLE FileHandle,

                 HANDLE ExistingCompletionPort,ULONG_PTR CompletionKey,

                 DWORD NumberOfConcurrentThreads);

              主要作用是创建IOCP和将SOCKET绑定到IOCP。

         2.BOOL GetQueuedCompletionStatus(HANDLE CompletinonPort,

                 LPDWORD lpNumberOfBytes,PULONG_PTR lpCompletionKey,

                 LPOVERLAPPED* lpOverlapped,DWORD dwMilliseconds);

               IOCP内部会管理线程池的,

                    而线程则需要通过这个函数来查询完成的操作;

    --注意事项:

        创建线程的数量一般配置为内核的数量或内核数量的2倍;

    ·小结:

        如果需要深入理解IOCP的话需要学习前摄器模式。

  • 相关阅读:
    获取本机IP地址[JavaScript / Node.js]
    python 优雅的解析 jsonp
    Ext.jsTree 向子节点添加叶子节点
    LeetCode面试题 08.05. 递归乘法:A * B 就是B个A相加
    LeetCode第235题:二叉搜索树的最近公共祖先——到两个点路径交集的最后一个元素
    InvalidMongoDbApiUsageException之重复的字段条件
    leetcode第6题:Z字形变换--直接模拟求解法
    Arch Linux 安装指南
    从Windows文件夹到Linux分区
    华为 服务器 存储相关资料
  • 原文地址:https://www.cnblogs.com/davidyang2415/p/2452022.html
Copyright © 2011-2022 走看看