网络模型第六讲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. 我的 FPGA 学习历程(12)—— 电子钟项目准备

    初学 FPGA 的时候,我们总是存在很多疑问,比如:xilinx 和 altera 的 FPGA 那种比较好.verilog 语言被如何综合成具体硬件电路.RTL 级电路是什么意思等等.现在我们就不会 ...

  2. MyBatis3系列__04CRUD以及参数处理

    本文将会简单介绍一下MyBatis的CRUD以及结合源码讲解一下MyBatis对参数的处理. 作为一个ORM框架,最基本的使用也就是CRUD了,MyBatis提供了两种方法:xml配置文件和动态注解. ...

  3. Day3----《Pattern Recognition and Machine Learning》Christopher M. Bishop

    其实今天只花了一点点时间来学习这本书, 如果模型的参数过多,而训练数据又不足够多的话,就会出现overfitting. overfitting可以通过regularization来解决,贝叶斯方法也可 ...

  4. 调用获取学生信息的接口,保存到excel里面

    # 2.http: // doc.nnzhp.cn / index.php?s = / 6 & page_id = 14# 调用获取学生信息的接口,保存到excel里面 import requ ...

  5. hanlp大辞典

    hanlp加一个很大的词典时候遇到的问题: ,然后改为5g,5g,问题得到解决. 但是运行后还有一个问题是: 重新改为10g,10g,问题得到解决. 也就是给java虚拟机分配的内存大点.

  6. SQL Server数据库可能遇到的报错

    1.操作附加操作时报错: 可能的解决方法: 退出数据库,换Windows身份验证登录,就可以了 2.插入语句报错: 1) 2)

  7. spring-security权限管理学习目标

    1.SVN基本介绍: 1.svn基本的概念 2.svn架构 3.svn下载与安装 4.svn搭建与基本操作 2.svn基本操作 1.操作1 2.操作2 3.冲突产生 4.冲突解决 3.SVN在IDEA ...

  8. 上传文件格式,及headers设置

    file[]:(binary)文件格式,传过去的参数自然是query string parameters  形式,当然也有纯的formData格式 formData格式就是将所有的参数append到p ...

  9. LeetCode编程训练 - 滑动窗口(Sliding Window)

    滑动窗口基础 滑动窗口常用来解决求字符串子串问题,借助map和计数器,其能在O(n)时间复杂度求子串问题.滑动窗口和双指针(Two pointers)有些类似,可以理解为往同一个方向走的双指针.常用滑 ...

  10. ABP入门系列(2)——领域层创建实体

    ABP入门系列目录--学习Abp框架之实操演练 这一节我们主要和领域层打交道.首先我们要对ABP的体系结构以及从模板创建的解决方案进行一一对应.网上有代码生成器去简化我们这一步的任务,但是不建议初学者 ...