网络模型第六讲Select模型

一丶Select模型是什么

    以前我们讲过一个迭代模型.就是只服务一个客户端连接.但是实际网络编程中.复杂的很多. 比如一个 C/S架构程序 (客户端/服务端) 客户端很多的情况下.都要连接服务器.

不可能一个服务器只服务一个客户端. 就像现在很火的一款游戏 .PUBG. 绝地求生. 他就是 CS结构程序. 玩的人很多.不可能买了很多很多服务器吧.所以我们就要写模型. 来管理这些客户端的Socket

并对去进行读写操作. 当前 Select模型只针对小网络程序使用. 不可能应用到游戏上. 因为它能管理的Socket 实在有限. 如果是Windows的话可能以后会接触到事件模型.消息模型.以及IOCP模型.

其实说白了就是对Socket进行管理.有效的进行读写.减少开销. 随着模型等级越高.所需要的知识点就越多.就越来越困难.

二丶Select 方法

   socket 套接字为我们提供了一个Select 方法.

int WSAAPI select(
int nfds, //默认为0
fd_set *readfds, //一个指针集合.. 针对读操作 accept,recg
fd_set *writefds, //针对写操作 connect send
fd_set *exceptfds, //针对出现的异常
const timeval *timeout //超时设置,为NULL就是一直等待结果.
);
返回值:
  1超时返回0
  2.出错返回 SOCKET_ERROR

其中FD_SET是一个结构体.

typedef struct fd_set {
u_int fd_count; /* how many are SET? */ 有多少套接字
SOCKET fd_array[FD_SETSIZE]; /* an array of SOCKETs */ 套接字的数据
} fd_set; FD_SETSIZE =
所以说不能针对大网络.因为只有64个.当然你可以更改.不过更改之后还不如用更好的模型.

常用的方法;

  FD_ZERO 清零

  FD_SET    添加套接字  也就是往数组里面添加指针

  FD_ISSET 校验函数.如果参数是集合的成员.则返回 非0 ,否则返回0

int getsockopt(
SOCKET s, //查询的套接字
int level, //选项的等级. SOL_SOCKET IPPROTO_TCP 原始套接字还是
int optname, //SOCKET选项名字 SO_ERROR SO_ACCEPTCONN
char *optval, //用于接受数据的缓冲区
int *optlen //缓冲区大小
);
函数作用: 查看套接字的状态
返回值: 成功0 失败 SOCKET_ERROR

具体作用可以查询MSDN

select 函数的作用:

  上面说了怎么多.可能大家就很晕.该如何编写代码. 编写代码前说一下.或许能豁然开朗.

其实我们 定义了数组(集合) 当有事件来的时候.select会返回. 返回的时候.会把我们集合里面的值进行设置. 这样我们可以对集合的值进行判断.如果是accept 则调用accept.

代码如下:

  

// Server.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib") int main()
{ WSADATA wsaData;
int iResult;
u_long iMode = ; iResult = WSAStartup(MAKEWORD(, ), &wsaData);
if (iResult != NO_ERROR)
printf("Error at WSAStartup()\n"); //-------------------------
// Create a SOCKET object.
SOCKET m_socket;
m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_socket == INVALID_SOCKET) {
printf("Error at socket(): %ld\n", WSAGetLastError());
WSACleanup();
return ;
} sockaddr_in hServerAddr;
hServerAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
hServerAddr.sin_family = AF_INET;
hServerAddr.sin_port = htons(); bind(m_socket, (sockaddr *)&hServerAddr, sizeof(hServerAddr)); //监听 listen(m_socket, ); //主要是进行连接的时候.代码不一样了.因为是非阻塞.所以返回的错误是资源暂时不可用.
sockaddr_in hClientAddr;
int nAddrSize = sizeof(hClientAddr);
SOCKET hClientSocket; fd_set Read, Write, Except; //定义三个集合.并且清零 FD_ZERO(&Read);
FD_ZERO(&Write);
FD_ZERO(&Except); //添加SOCKET 到集合中
FD_SET(m_socket, &Read);
FD_SET(m_socket, &Write);
FD_SET(m_socket, &Except); //使用Select 进行监听 无限监听
int nRet = select(, &Read, &Write, &Except,NULL); //如果有读操作.则Read集合则被改变. nRet = FD_ISSET(m_socket, &Read);//只判断读 char szBuf[0x1000] = { };
if (SOCKET_ERROR != nRet)
{
//我们就可以进行接收了.因为读操作只有接收.不可能是Recv
hClientSocket = accept(m_socket, (sockaddr*)&hClientAddr, &nAddrSize);
//继续进行清零.看看是否是读操作还是写操作. recv(hClientSocket, szBuf, 0x1000, );
FD_ZERO(&Read);
FD_ZERO(&Write);
FD_ZERO(&Except); //讲客户端套接字跟服务端套接字都放到集合中. FD_SET(m_socket, &Read);
FD_SET(m_socket, &Write);
FD_SET(m_socket, &Except); FD_SET(hClientSocket, &Read);
FD_SET(hClientSocket, &Write); // 如果都设置了.那么在此进行Select监听的时候.服务端套Read集合则为2.因为要接受.客户端的Write则为1.因为他发送了send
FD_SET(hClientSocket, &Except); nRet = select(, &Read, &Write, &Except, NULL); nRet = FD_ISSET(hClientSocket, &Write); //客户端的写操作回来.所以影响的是客户端的write 服务端的不影响. int nRet2 = FD_ISSET(m_socket, &Write); }
return -;
}

当有客户端连接的时候.我们的集合就重置了.

例如下图:

可以看到套接字是一个f4 有一个.所以下方我们进行判断是否是读操作.如果是读操作我们就进行接受连接

接受连接之后.我们把客户端的套接字也设置到集合中.当监听客户端操作的时候.写操作就会来了.

总结一下:

    1.send recv connect accept 都是一个状态.

    2.slecet 会根据这些来设置我们集合中数组的状态.

    3.我们根据判断集合中数组的状态.对其进行操作即可.

如果出现异常.我们就需要用

getsockopt 来检索错误值了.
因为我们使用的FD_xxx都是宏. 如果在使用GetLastError 则会出现错误.结果不准确. 所以直接使用这个函数进行错误代码的获取.
例子:
if (FD_ISSET(hSocket,&Except))  //如果出现异常了.
{
int nErrCode;
int nErrCodeLen;
getsocket(hSocket,SOL_SOCKET,SO_ERROR,&nErrcode,&nErrcodelen);
}

网络编程第六讲Select模型的更多相关文章

  1. Linux 网络编程的5种IO模型:多路复用(select/poll/epoll)

    Linux 网络编程的5种IO模型:多路复用(select/poll/epoll) 背景 我们在上一讲 Linux 网络编程的5种IO模型:阻塞IO与非阻塞IO中,对于其中的 阻塞/非阻塞IO 进行了 ...

  2. Linux 网络编程的5种IO模型:信号驱动IO模型

    Linux 网络编程的5种IO模型:信号驱动IO模型 背景 上一讲 Linux 网络编程的5种IO模型:多路复用(select/poll/epoll) 我们讲解了多路复用等方面的知识,以及有关例程. ...

  3. 脑残式网络编程入门(六):什么是公网IP和内网IP?NAT转换又是什么鬼?

    本文引用了“帅地”发表于公众号苦逼的码农的技术分享. 1.引言 搞网络通信应用开发的程序员,可能会经常听到外网IP(即互联网IP地址)和内网IP(即局域网IP地址),但他们的区别是什么?又有什么关系呢 ...

  4. Linux 网络编程的5种IO模型:异步IO模型

    Linux 网络编程的5种IO模型:异步IO模型 资料已经整理好,但是还有未竟之业:复习多路复用epoll 阅读例程, 异步IO 函数实现 背景 上一讲< Linux 网络编程的5种IO模型:信 ...

  5. python网络编程——IO多路复用之select

    1 IO多路复用的概念 原生socket客户端在与服务端建立连接时,即服务端调用accept方法时是阻塞的,同时服务端和客户端在收发数据(调用recv.send.sendall)时也是阻塞的.原生so ...

  6. Linux 网络编程的5种IO模型:阻塞IO与非阻塞IO

    背景 整理之前学习socket编程的时候复习到了多路复用,搜索了有关资料,了解到多路复用也有局限性,本着打破砂锅问到底的精神,最终找到了关于IO模型的知识点. 在<Unix网络编程>一书中 ...

  7. c++ 网络编程(六)LINUX下 socket编程 多播与广播 实现一次发送所有组客户端都能接收到

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9614288.html 一.多播 锲子:有这么一种情况,网络电台可能需要同时向成千上万的用户传输 ...

  8. Netty学习第三章 Linux网络编程使用的I/O模型

    一.同步阻塞IO:blocking IO(BIO) 1.过程分析: 当进程进行系统调用时,内核就会去准备数据,当数据准备好后就复制数据到内核缓冲器,复制完成后将数据拷贝到用户进程内存,整个过程都是阻塞 ...

  9. 网络编程学习——Linux epoll多路复用模型

    前言 后端开发的应该都知道Nginx服务器,Nginx是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器.后端部署中一般使用的就是Nginx反向代理技术. ...

随机推荐

  1. Chrome开发者工具面板

    Chrome开发者工具面板 面板上包含了Elements面板.Console面板.Sources面板.Network面板.Timeline面板.Profiles面板.Application面板.Sec ...

  2. Nginx的虚拟主机配置

    虚拟主机技术能够让同一台服务器.同一组Nginx进程上运行多个网站,降低了资金和服务器资源的损耗.Nginx可以配置三种类型的虚拟主机,本文就是主要介绍这三种虚拟主机配置方式. 配置基于IP的虚拟主机 ...

  3. [LeetCode] Find And Replace in String 在字符串中查找和替换

    To some string S, we will perform some replacement operations that replace groups of letters with ne ...

  4. Flutter 获取服务器数据

    文档 文档版本有些老 使用 dio 来获取数据 demo import 'dart:io'; import 'dart:convert'; import 'package:flutter/materi ...

  5. Tomcat问题

    1 Tomcat控制台中文乱码 打开tomcat/conf/logging.properties 找到java.util.logging.ConsoleHandler.encoding = UTF-8 ...

  6. Oracle 函数 Function

    定义 函数用于计算和返回一个结果值,把经常需要进行的计算写成函数,函数的调用是表达式的一部分.     函数与过程在创建的形式上有些相似,也是编译后放在内存中供用户使用.     函数必须有一个返回值 ...

  7. IDEA环境下SSM整合------注解开发

    根据前一篇文章的步骤,目前项目进度应该是:核心过滤器配置完成.DispatcherServlet和ContextLoader配置完成.数据库dataSource配置完成.视图解析器配置完成.Mappe ...

  8. 手机touch事件及参数【转】(自己懒得写了,找了一篇摘过来)

    [html5构建触屏网站]之touch事件 前言 一个触屏网站到底和传统的pc端网站有什么区别呢,交互方式的改变首当其冲.例如我们常用的click事件,在触屏设备下是如此无力. 手机上的大部分交互都是 ...

  9. 让 ComboBox 的每个栏目显示不同颜色

    在一般的应用程式中,使用 ComboBox 提供下拉选单的功能,让使用者选择不同项目,一般而言, ComboBox 的项目没有什么特别的,但在特定的应用程式中,有时候会希望每个项目有一些效果呈现,例如 ...

  10. tag cloud的相关资料

    http://reverland.org/python/2013/01/28/visualize-your-shell-history/ https://github.com/reverland/sc ...