select用途:在一段时间内,监听用户感兴趣的文件描述符上的可读可写和异常等时间。
对于select函数的接口:
int select(int nfds,fd_set* readfds,fd_set* writefds,fd_set* exceptfds,struct timeval* timeout);
nfds表示监听的文件描述符总数,他是监听的最大值加1,目的是为了节省时间
后面三个参数是可读可写和异常,最后一个参数是等待时间,如果给timeout变量的成员都传递0那么就立即返回,NULL就无限等待,若是一个struct timeval结构体,那么时间间就自己进行设定,具体的后续操作可以通过返回值来判定。
fd_set是一个结构体,最多监听1024个,这是select的默认最大。
关于select的返回值,如果超时切没有任何描述符就绪,那么返回0,如果失败则返回-1,如果成功那么就返回就绪文件描述符的总数,如果在等待期间接收到了信号那就返回-1。
select对于接收带外数据也普通数据 都可使得select返回,但是select处于不同的就绪状态,前者可读,后者异常。
关于select监听其他的进程给自己发送信息的代码如下:
#include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main()
{
int sockfd = socket(AF_INET,SOCK_STREAM,0);
assert(sockfd!=-1);
struct sockaddr_in saddr,caddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(6500);
saddr.sin_addr.s_addr = inet_addr("192.168.1.11");
int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
assert(res!=-1);
int ret = listen(sockfd,5);
assert(ret!=-1);
int len = sizeof(caddr);
int c = accept(sockfd,(struct sockaddr*)&caddr,&len);//c已经在这里定义了所以只可以监控一个的,如果你想多个的可以自己修改
fd_set rdset;
while(1)
{
FD_ZERO(&rdset);//clear
FD_SET(c,&rdset);//set read
int n = select(c+1,&rdset,NULL,NULL,0);//always
if(n<0)//error
{
break;
}
if(FD_ISSET(c,&rdset))
{
char buff[128] = {0};
int ret = recv(c,buff,127,0);
if(ret <= 0)//如果客户端关闭,返回0直接退出
{
printf("client over!\n");
break;
}
printf("%s",buff);
}
}
close(c);
close(sockfd);
return 0;
}
相应的客户端代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc,char *argv[])
{
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(6500);//转换成大端
saddr.sin_addr.s_addr = inet_addr("192.168.1.11");
//要用就必须先运行起来
int res = connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));//链接到服务端上面
assert(res!=-1);
//执行到这个地方说明三次握手完成
while(1)
{
printf("input:\n");
char buff[128] = {0};
fgets(buff,128,stdin);//fgets会用到空格回车
if(strncmp(buff,"end",3)==0)
{
break;
}
send(sockfd,buff,strlen(buff),0);//把收到的讯息再发送出去
memset(buff,0,128);
}
close(sockfd);//关闭
return 0;
}
个人总结,如果有不对的欢迎指正