<>select Interface introduction :

select The purpose of the system call is : Within a specified period of time , Listen for the readability of the file descriptor of interest to the user , Events such as writable and exception

<>select Use case :

use select Process multiple TCP Client for , complete TCP Concurrent processing of server

Server side :
#include <stdio.h> #include <stdlib.h> #include <assert.h> #include <string.h>
#include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include
<arpa/inet.h> #include <sys/select.h> #include <sys/types.h> #define DATALENTH
1024 #define MAX_FD 128 // Initialize server-side socket int socket_init() { int sockfd=socket(
AF_INET,SOCK_STREAM,0); if(sockfd==-1) { return -1; } struct sockaddr_in saddr;
memset(&saddr,0,sizeof(saddr)); saddr.sin_family=AF_INET; saddr.sin_port=htons(
7000); saddr.sin_addr.s_addr=inet_addr(""); int res=bind(sockfd,(struct
sockaddr*)&saddr,sizeof(saddr)); if(res==-1) { return -1; } res=listen(sockfd,5)
; assert(res!=-1); return sockfd; } // Initializes the socket array of the server void InitFds(int fds[],int n)
{ int i=0; for(;i<n;i++) { fds[i]=-1; } } // Adds a descriptor to the socket array of the server void AddFds(int fds
[],int fd,int n) { int i=0; for(;i<n;i++) { if(fds[i]==-1) { fds[i]=fd; break; }
} } // Deletes the specified descriptor from the socket array of the server void DelFds(int fds[],int fd,int n) { int i=0; for(;i<
n;i++) { if(fds[i]==fd) { fds[i]=-1; break; } } }
// Set the socket descriptor in the array to fd_set Variable , And returns the current maximum file descriptor int SetFdToFdset(fd_set* fdset,int fds[]
,int n) { FD_ZERO(fdset); int i=0,maxfd=fds[0]; for(;i<n;i++) { if(fds[i]!=-1) {
FD_SET(fds[i],fdset); if(fds[i]>maxfd) { maxfd=fds[i]; } } } return maxfd; }
// Get the connection of the client void GetClientLink(int sockfd,int fds[],int n) { struct sockaddr_in
caddr; memset(&caddr,0,sizeof(caddr)); int len=sizeof(caddr); int c=accept(
sockfd,(struct sockaddr*)&caddr,&len); if(c<0) { return ; } printf("A client
connect successful\n"); AddFds(fds,c,n); } // Processing client data void DealClientData(int fds
[],int n,int c) { char buff[DATALENTH]={0}; int num=recv(c,buff,DATALENTH-1,0);
if(num<=0)// If receiving content fails , This descriptor is removed from the fds Delete inside { DelFds(fds,c,n); close(c); printf("A
Client disconnection\n"); } else// Received successfully , Then print out the corresponding data { printf("buff(%d):%s\n",c,buff
); send(c,"ok",2,0); } } // handle select Ready event returned void DealReadyEvent(int fds[],int n,
int sockfd,fd_set* fdset) { int i=0; for(;i<n;i++) { if(fds[i]!=-1&&FD_ISSET(fds
[i],fdset)) { if(fds[i]==sockfd) { GetClientLink(sockfd,fds,n); } else {
DealClientData(fds,n,fds[i]); } } } } int main() { int sockfd=socket_init(); if(
sockfd==-1) { return -1; } fd_set readfds; int fds[MAX_FD]; InitFds(fds,MAX_FD);
AddFds(fds,sockfd,MAX_FD); while(1) { int maxfd=SetFdToFdset(&readfds,fds,MAX_FD
); struct timeval time; time.tv_sec=5;//5 second time.tv_usec=0;// Microsecond int n=select(
maxfd+1,&readfds,NULL,NULL,&time); if(n<0)// fail { printf("select error\n"); break
; } else if(n==0)// overtime { printf("time out\n"); continue; } DealReadyEvent(fds,
MAX_FD,sockfd,&readfds); } exit(0); }
client :
#include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include
<netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #
include <assert.h> int main() { int sockfd=socket(AF_INET,SOCK_STREAM,0); assert
(sockfd!=-1); struct sockaddr_in saddr; memset(&saddr,0,sizeof(saddr)); saddr.
sin_family=AF_INET; saddr.sin_port=htons(7000); saddr.sin_addr.s_addr=inet_addr(
""); int res=connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
assert(res!=-1); while(1) { printf("please input:\n"); char buff[1024]={0};
fgets(buff,1024,stdin); if(strncmp(buff,"end",3)==0) { break; } int n=send(
sockfd,buff,strlen(buff),0); if(n<=0) { printf("send error\n"); break; } memset(
buff,0,1024); n=recv(sockfd,buff,1024,0); if(n<=0) { printf("recv error\n"); }
printf("buff=%s\n",buff); } close(sockfd); exit(0); }
Operation results :

<> Attention problem :

If the receiver can only receive one character at a time , So if the client sends “hello”, The server will receive a “h”, problem : Remaining characters “ello” Will it be received ?

The answer is :
Server side :select It will constantly remind the server to receive the contents of the buffer , So the rest "ello" Will be received at one time , When the contents of the buffer are accepted , Then process the contents of the next socket .
client : According to code , The server side receives one time , It will be sent to the client once “ok”,
When the server receives a “h”, Send a message to the client “ok”.
Subsequent “ello” The server will also receive , It sends the rest to the client 5 individual “ok" In client receive buffer , When waiting for the client to receive the next time, it will send the last time 5 individual “ok” All receive .