当前位置:网站首页>[understand one article] FD_ Use of set
[understand one article] FD_ Use of set
2022-07-02 04:33:00 【Ou Enyi】
title: FD_SET Use
description: FD_SET、FD_ZERO、FD_ISSET、FD_CLR as well as select
Check it casually , You can see that it's right FD_SET The description is as follows :
One
longAn array of types , Provide toselect()A data structure used by the mechanism . The main function is to establish contact . Each of these array elements can be associated with Any open handle (socket Handle 、 file 、 name pipes 、 Device handle, etc ) Make connections . But this kind of connection building work must be done by programmers themselves .The small white , For example, people like me will wonder , What is the purpose of setting this connection ?
“ It can be understood as giving to Open handle Added a logo .( read or Write or abnormal ) The logo of . For the time being, you just need to know that we can pass
fd_set( A lowercase letter ) To judge socket The operation of .ad locum , We raise the following questions , The order from simple to slightly complex is as follows :
fd_setWhat is it? ?FD_SET、FD_ZERO、FD_ISSET、FD_CLRWhat are the functions of ?- How to use
fd_set( combinationselect()) Determine the state of the handle ?In this paper, the above three issues , Answer and record . Experimental environment (win10+vs2017+v141)
socket The relevant file headers used are roughly as follows :
#include <iostream>
#include <WinSock2.h>
#include <stdio.h>
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")
1. fd_set What is it? ?
We'll start with ,fd_set It's a long An array of types . We can think of this as a large byte array .
Let's start with a short piece of code to understand fd_set This array .
Code 1-1
int main()
{
SOCKET socket = {
0}; // Define a socket object
fd_set fdset = {
0}; // Declare and define , If the initial value is not assigned ,fd_set Random values are stored in
FD_ZERO(&fdset);
FD_SET(1, &fdset); // ’ contact ‘ That's where it came into being , following 4 One operation will produce others 4 A connection
FD_SET(2, &fdset);
FD_SET(3, &fdset);
FD_SET(7, &fdset);
FD_SET(socket, &fdset);
int isset = FD_ISSET(socket, &fdset); // ’ contact ‘ That's where it came into being
printf("isset = %d\n", isset); // isset = 1
FD_CLR(socket, &fdset);
isset = FD_ISSET(socket, &fdset); // isset = 0
printf("isset = %d\n", isset);
return 0;
}
The debugging screenshot is as follows :
You can see ,fd_set Is a length of 64 Array of , Because the code is initialized , So everyone is 0. Calling FD_SET In the process of , Equivalent to in a vector.push_back The operation of .
among , How many in the world set, It is through fd_count To decide . Above screenshot , Although it seems that fd_array The only valid values are 1、2、3、7, But actually fd_count The value of is 5. It's not that it's not bound to scoket, But because socket Is initialized to 0 了 , So actually fdset The valid array saved by the variable is [1,2,3,7,0].
2. FD_SET、FD_ZERO、FD_ISSET、FD_CLR What are the functions of ?
First of all, we need to know , The above four macro interfaces provided ( Note that macro Interface ) It must be used to operate fd_set Of . The specific functions are as follows :
Code 2-1
// there fd The actual use is based on Handle Pass in
FD_ZERO(fd_set *fdset); // take set Clear so that the set does not contain any fd
FD_SET(int fd, fd_set *fdset); // take fd Join in set aggregate
FD_CLR(int fd, fd_set *fdset); // take fd from set Clear from set
FD_ISSET(int fd, fd_set *fdset); // testing fd Whether in set Collection , If not, return to 0
The correct use process is :
call
FD_ZEROWill afd_setAll bits of the variable are set to0. To turn on a bit in the descriptor set , You can callFD_SET. callFD_CLRYou can clear one . Last , You can callFD_ISSETTest whether a pointer in the descriptor set is turned on .
Or combination 1-1 Code for :
FD_ZEROIs to put the currentfd_setAll digits are set to0.FD_SETImplements handles andfd_setOf contact , You can putfd, That is to sayHandleAdd tofd_setin .FD_CLRKnow what is bound contact , Pay attention : Only those you pass in are cleared herefdandfd_setThe connection between . It should be noted that ,FD_CLRThe operation of is similar to the deletion of linked list nodes ( Subsequent nodes will fill in the deleted nodes ). For example, the code in the first question ;Code
2-2int isset = FD_ISSET(socket, &fdset); // printf("isset = %d\n", isset); // isset = 1 FD_CLR(socket, &fdset); isset = FD_ISSET(socket, &fdset); // isset = 0 printf("isset = %d\n", isset);Code
2-2The first 3 That's ok , Just clear the previous textFD_SET(socket, &fdset);Binding connection , But it doesn't involve1、2、3、7AndfdsetThe connection between . How to judge this connection ? It is throughFD_ISSETFD_ISSETMacro interface . As shown in the above code . If the bound connection is in, return 1, conversely , Then return to 0.- Calling
FD_ISSETafter ,isset The value of is 1 - call
FD_CLRafter ,isset The value of a 0
- Calling
3. How to use fd_set( combination select()) Determine the state of the handle ?
To understand how to judge , I still have to go back to
select()function
Moving books 《UNIX Environment advanced programming 》 In a Book I/O Multiplex The chapters are explained very clearly
select() The function prototype :
Code 3-1
int select( int maxfdpl, fd_set *restrict readfds,
fd_set *restrict writefds,fd_set *restrict exceptfds,
struct timeval *restrict typfr);
// Return value ∶ Number of descriptors ready ; In case of overtime , return 0; If something goes wrong , return -1
In all POSIX On compatible platforms ,select Function enables us to perform I/O Multiplex . Pass to select The parameters of tell the kernel ∶
What we care about is ;
For each descriptor, the conditions we are concerned about ( Whether you want to read from a given descriptor , Do you want to write a given descriptor , Whether to care about the exception condition of a given descriptor );
How long are you willing to wait ( You can wait forever 、 Wait for a fixed time or not at all ).
select return , The kernel tells us ∶
- The total number of descriptors prepared ;
- For reading 、 Write or exception this 3 Each of these conditions , Which descriptors are ready .
Use this return message , You can call the corresponding I/O function ( It's usually read or write), And make sure that the function doesn't block .
If you want to set socket by Non blocking The state of , You need to call
ioctlsocket(m_Socket, FIONBIO, &ul);To set up . Among themulIt's aunsigned longVariable of type , In this function interface ,ul == 1Indicates to set the currentm_SocketIs non blocking .
This paper focuses on select() The three parameters in the middle of the function readfds、writefds、exceptfds( The first parameter is also important ). These three parameters are pointers to the descriptor set , The descriptor set illustrates what we care about Can be read 、 Can write 、 abnormal The combination of . As shown in the figure below :

select()In the middle of the 3 Any one of the parameters ( Or all ) It can be a null pointer , You can do this when you don't need to operate to judge the abnormal reading and writing . If 3 Every pointer isNULL, beselectProvides a ratiosleepMore accurate timer .( What do you mean ?sleep Wait for an integer second , and select The waiting time can be less than 1 second , Its actual accuracy depends on the system clock .)select()The first parameter ofmaxfdp1It means “ Maximum file descriptor number plus 1”. You still have to understand a concept first , namelyfd_setEach bit of can only be used once , Only one state can be marked . To avoid repeated application , The following code , You need to control through the first parameter . That's the first parametermaxfdp1. How to choose the first parameter value ?- Set to
FD_SETSIZE. This is a <sys/select.h> A constant of , It specifies the maximum number of descriptors ( Usually 1024). But in general , The number is too large , The general procedure is 3~10 A descriptor . So in general , Select manual assignment . - Specify manually , The following code belongs to manual assignment . In all descriptor sets , Select the maximum number of descriptors we are interested in . In the following code , The maximum number of descriptors specified is 3, therefore
selectThe first argument to the function is4(= 3+1), That is, the maximum descriptor number value plus 1.
Code
3-2- Set to
fd_set readset, writeset;
FD_ZERO(&readset);
FD_ZERO(&writeset);
FD_SET(0, &readset);
FD_SET(3, &readset);
FD_SET(1, &writeset);
FD_SET(2, &writeset);
select(4, &readset, &writeset, NULL, NULL); // The department of select It will return -1
Such as code 3-2 After setting readset、writeset As shown in the figure below :

select() Yes 3 Possible return values :
- Return value
-1It means that something has gone wrong . It's possible , for example , A signal is captured when none of the specified descriptors are ready . In this case , A descriptor set is not modified . Code3-2It will return-1 - Return value
0Indicates that the descriptor is not ready . If none of the specified descriptors are ready , The appointed time has passed , Then this will happen . here , All descriptor sets are not modified . - One
Positive return valueDescribes the number of descriptors that have been prepared . At this value 3 The sum of the prepared descriptors in the descriptor set , So if the descriptor is ready to read and write , Then it will be counted twice in the return value . under these circumstances ,3 The bits that are still open in the descriptor set correspond to the prepared descriptor .
about “ Get ready ” The meaning of should be explained more specifically .
- If you read the collection (readfds) A descriptor in read The operation will not block , This descriptor is considered ready .
- If you write a set (writefds) A descriptor in write The operation will not block , This descriptor is considered ready .
- For exception condition set (exceptfds) A descriptor in has a pending exception condition , This descriptor is considered ready . Now? , Abnormal conditions include ∶ Data that reaches out of band on the network connection , Or some conditions occur on the pseudo terminal in packet mode .(Stevens【1990】 Of 15.10 The latter condition is described in section .)
- For reading 、 Write and exception conditions , The file descriptor of a normal file always returns ready .
Blocking a descriptor does not affect select Is it blocked , It's important to understand this . in other words , If you want to read a non blocking descriptor , And take the timeout value as 5 Second call select, be select It's blocked at most 5s. Similar , If you specify an infinite timeout value , When the descriptor data is ready , Or before capturing a signal ,select It will keep blocking .
If you encounter the end of a file on a descriptor , be select The descriptor will be considered readable . And then call read, It returns 0, This is a UNIX The system indicates how to reach the end of the file .( Many people mistakenly believe that , When the end of the file is reached ,select Will indicate an abnormal condition .)
For the above 3 Medium condition , The complete code is as follows :
You need to open a service at the remote end , You can use Huawei IPOP Tools .
Code 3-3
#include <iostream>
#include <WinSock2.h>
#include <stdio.h>
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")
using namespace std;
int main()
{
WSADATA wsa;
WSAStartup(MAKEWORD(2, 2), &wsa);
SOCKADDR_IN addrServer;
SOCKET Socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
fd_set readset, writeset;
addrServer.sin_addr.S_un.S_addr = inet_addr("192.168.3.16");
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons(6000);
DWORD dwResult = connect(Socket, (SOCKADDR*)&addrServer, sizeof(SOCKADDR));
FD_ZERO(&readset);
FD_ZERO(&writeset);
FD_SET(Socket, &readset);
FD_SET(Socket, &writeset);
/* int isset = FD_ISSET(Socket, &readset); // isset = 0 printf("isset = %d\n", isset); isset = FD_ISSET(Socket, &writeset); // isset = 0 printf("isset = %d\n", isset); */
int nRet = select(0, &readset, &writeset, NULL, NULL);
cout << "The Ret of Select is " << nRet << endl;
return 0;
}
Output :
So what the whole article is talking about read 、 Write 、 abnormal how ?
The answer is FD_ISSET.
Before use, we pass
FD_SETTo establish this connection between reading and writing exceptionsselect()It will be modified whenfd_setValue , And the modified value is what we can judge . Such as code code3-3, We can do it in select Then add judgment conditionsif (!FD_ISSET(m_Socket, &readset)) { cout << "sock not in readset!" << endl; } if (FD_ISSET(m_Socket, &writeset)) { cout << "sock not in writeset!" << endl; } if (FD_ISSET(m_Socket, &exceptset)) { cout << "getsockopt fail!" << endl; }At this time, you can judge the operation of the handle .
I don't say much nonsense , Go directly to the scene :
Because there is no read operation , So it only marks the operation of writing .
That's about
fd_setDetailed description of .To avoid hurting people's children , Such as incorrect , Please comment or write a private letter to correct .
Add :
Reference material :
- 《unix Advanced environment programming 》
- win32 Official documents
边栏推荐
- CorelDRAW Graphics Suite2022免费图形设计软件
- Thinkphp6 limit interface access frequency
- Pytoch --- use pytoch for image positioning
- 记录一次Unity 2020.3.31f1的bug
- [C language] basic learning notes
- Yyds dry inventory compiler and compiler tools
- Markdown编辑语法
- The solution to the complexity brought by lambda expression
- How to solve the problem that objects cannot be deleted in Editor Mode
- Okcc why is cloud call center better than traditional call center?
猜你喜欢

6月书讯 | 9本新书上市,阵容强大,闭眼入!

C language practice - binary search (half search)

Play with concurrency: what's the use of interruptedexception?
![[source code analysis] NVIDIA hugectr, GPU version parameter server - (1)](/img/e3/fc2e78dc1e3e3cacbd1a389c82d33e.jpg)
[source code analysis] NVIDIA hugectr, GPU version parameter server - (1)

MySQL advanced SQL statement 2

Leetcode merge sort linked list

Why can't you remember when reading? Why can't you remember- My technology learning methodology

Spring recruitment of Internet enterprises: Kwai meituan has expanded the most, and the annual salary of technical posts is up to nearly 400000

深圳打造全球“鸿蒙欧拉之城”将加快培育生态,优秀项目最高资助 1000 万元

10 minutes to understand CMS garbage collector in JVM
随机推荐
Exposure X8 Standard Version picture post filter PS, LR and other software plug-ins
Introduction to vmware workstation and vSphere
Wechat applet map annotation
Why can't you remember when reading? Why can't you remember- My technology learning methodology
BGP experiment the next day
Thinkphp內核工單系統源碼商業開源版 多用戶+多客服+短信+郵件通知
June book news | 9 new books are listed, with a strong lineup and eyes closed!
Websites that it people often visit
Learn what definitelytyped is through the typescript development environment of SAP ui5
Wechat applet calculates the distance between the two places
Fluent icon demo
Record the bug of unity 2020.3.31f1 once
Pytorch---使用Pytorch实现U-Net进行语义分割
MySQL advanced SQL statement 2
Target free or target specific: a simple and effective zero sample position detection comparative learning method
[C language] Dynamic Planning --- from entry to standing up
How to solve the problem that objects cannot be deleted in Editor Mode
cookie、session、tooken
Pytoch --- use pytoch to predict birds
汇编语言中的标志位:CF、PF、AF、ZF、SF、TF、IF、DF、OF