select函数
intselect(int maxfd1, fd_set *readset, fd_set* writeset, fd_set *exceptset, conststruct timeval * timeout)
如果对某个条件不感兴趣的话,就直接置NULL就好了,如果三个套接字集都设置为NULL就生成了比sleep还要精确的休眠函数(精确到微秒)
maxfdp1是套接字的个数,也是最大fd+1,因为是fd是从0开始计数的
select函数返回跨所有描述子集的已准备好的位数,如果是timeout时间到了的话,就直接返回0,如果函数返回-1就说明出现了错误,一般都是因为被信号中断了的,调用perror函数来查看当前errno所代表的错误描述
套接字准备好的条件(即select函数返回)
读描述符集:1 是当内核中的套接字缓冲区的数据大于等于套接字接受缓冲区的低潮限度的时候(设置低潮限度是为了是应用层决定多少数据才能完成一项任务的,比如说低潮限度设置为5字节,应用层就是说,当该套接字内核缓冲区的数据至少是5个字节的时候,我才要接受,才能完成我应用层的某项业务)
2 就是读连接关闭,另一端发送了close或者shutdown操作所产成的Fin数据报
3 就是服务器发送rst数据报的时候,说我服务器没有该项服务,请重新建立连接
4 就是套接字发生错误的时候
写套接字集:1 当写到内核缓冲区的数据大于等于该套接字的低潮限度的时候
2 就是套接字发送了Fin数据报的时候,连接的写着一半关闭的时候在发发送数据的时候内核会给应用层SIGPIPE信号结束该进程
3 就是写套接字发生错误的时候
intshutdown(int sockfd ,int howto)
SHUT_RD 关闭套接字的读方向的连接,这个时候不再接受套接口中的数据并且留在套接口缓冲区的数据都将作废
SHUT_WR 关闭套接字发送的连接,当前留在套接口发送缓冲区的数据都被发送后,后跟正常的连接终止序列
SHUT_RDWR等效上面两个的综合体
int pselect(int maxfd, fd_set *rd, fd_set *wr, fd_set*err, const struct timespec *timeout,const sygset_t *sigmask)
structtimespec
{
time_t tv_sec;
long tv_nsec;//na miao
}
poll 和select函数一样这里就不详细讲解了
现在把客户端改写成select进行驱动的了:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <sys/select.h>
#include <sys/time.h>
#define SER_IP "127.0.0.1"
#define SER_PORT 9877
#define MAX_LINE 128
int max(int a, int b)
{
if(a>b)
{
return a;
}
else
{
return b;
}
}
void send_myself(int fd)
{
char tmp[MAX_LINE] = {0};
int size;
fd_set set;
FD_ZERO(&set);
FD_SET(fileno(stdin), &set);
FD_SET(fd,&set);
int max1 = max(fileno(stdin), fd)+1;
select(max1, &set, NULL, NULL, NULL);
if(FD_ISSET(fileno(stdin), &set))
{
if(fgets( tmp, MAX_LINE,stdin) == NULL)
{
shutdown(fd,SHUT_WR);
sleep(4);
exit(0);
}
write(fd, tmp, strlen(tmp));
}
if(FD_ISSET(fd, &set))
{
if(read(fd ,tmp, MAX_LINE) == 0)
{
exit(0);
}
fputs(tmp,stdout);
}
//fgets(tmp,MAX_LINE - 1,stdin);
//write(fd,tmp, strlen(tmp));
}
int main(int argc, char** argv)
{
int send_sk;
struct sockaddr_in s_addr;
socklen_t len = sizeof(s_addr);
send_sk = socket(AF_INET, SOCK_STREAM, 0);
if(send_sk == -1)
{
perror("socket failed ");
return -1;
}
bzero(&s_addr, sizeof(s_addr));
s_addr.sin_family = AF_INET;
//s_addr.sin_addr.s_addr = htonl(
inet_pton(AF_INET,SER_IP,&s_addr.sin_addr);
s_addr.sin_port = htons(SER_PORT);
if(connect(send_sk,(struct sockaddr*)&s_addr,len) == -1)
{
perror("connect fail ");
return -1;
}
while(1)
{
send_myself(send_sk);
}
}
周六日双休,爽