您的位置:首页 > 理论基础 > 计算机网络

linux select 网络模型

2015-11-08 21:31 686 查看
io模型:

  同步IO: 阻塞形式,非阻塞形式(轮询)、信号驱动IO、IO复用(select, poll, epoll);

  异步io:aio_read()

典型场景:

  1、客户端处理多种IO-------标准io 和网络io(套接字)

  2、server端既要处理监听套接字又要处理已连接的套接字

  3、一个服务器要处理TCP,又要处理UDP

  4、server端要处理多种服务多个协议;

  5、不管是网络套接字还是文件读写描述符均可处理;

#include <stdio.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#include <netinet/in.h>
#include <sys/socket.h>
#include <string.h>         //bzero()

int main()
{
int socketfd;
struct sockaddr_in  serv_addr;    //struct socket address internet
int i =0;
/** /usr/include/netinet/in.h
*  #define __SOCKADDR_COMMON(sa_prefix) \
*    sa_family_t sa_prefix##family)
*
*  struct sockaddr_in{
*      _SOCKADDR_COMMON(sin_); //展开宏sa_family_t  sin_family
*      int_port_t sin_port;
*      struct in_addr sin_addr;
*  }
*accept默认会阻塞进程,直到有一个客户连接建立后返回,
*它返回的是一个新可用的套接字,这个套接字是连接套接字。
*此时我们需要区分两种套接字,一种套接字正如accept的参数sockfd,它是监听套接字,
*在调用listen函数之后,一个套接字会从主动连接的套接字变身为一个监听套接字;
*而accept返回是一个连接套接字,它代表着一个网络已经存在的点点连接。
*在调用listen函数之后,一个套接字会从主动连接的套接字变身为一个监听套接字;
*而accept返回是一个连接套接字,它代表着一个网络已经存在的点点连接。
*自然要问的是:为什么要有两种套接字?原因很简单,如果使用一个描述字的话,
*那么它的功能太多,使得使用很不直观,同时在内核确实产生了一个这样的新的描述字.
*/
//struct sockaddr_in serv_addr;
//address family, socket_stream, 0:会自动选择type类型对应的默认协议
socketfd = socket(AF_INET,SOCK_STREAM, 0);
if(socketfd){

}

bzero((char*)&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;         //主机字节序
serv_addr.sin_port   = htons(7777);     //网络字节序
serv_addr.sin_addr.s_addr =htonl(INADDR_ANY);   //监听所有地址

if(bind(socketfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr))){

}

listen(socketfd, 100);

int maxfd;
fd_set allset, rset;
maxfd = socketfd;

FD_ZERO(&allset);           //将allset清零,使得集合中不含任何fd
FD_SET(socketfd, &allset);  //将socketfd加入allset集合

int sockfd, clilen, bytes;
struct sockaddr_in cli_addr;
char buffer[256];

while(1){
rset = allset;
       /*select第一个参数表示要检查的文件描述符的个数;比如最大值为5,因为
       *文件描述符是从0开始的,所以需要检查0,1,2,3,4,5这六个值;即最大值+1;
       */
if(select(maxfd+1, &rset, NULL, NULL, NULL)){

}

for(i=0; i<=maxfd; i++){
if(FD_ISSET(i, &rset)){     //一个个来判断是否被置位了
if(socketfd == i){      //监听套接字
clilen = sizeof(cli_addr);
sockfd = accept(socketfd, (struct sockaddr*)&cli_addr, (socklen_t*)&clilen);
if(sockfd<0){   //error
perror("accept error \n");
}
FD_CLR(i, &rset);   //清零
maxfd = maxfd>sockfd?maxfd:sockfd;
FD_SET(sockfd, &allset);

}else{                  //通信套接字
bzero(buffer, 256);
bytes = recv(i, buffer, 256, 0);
if(bytes <= 0){     //client端退出
FD_CLR(i, &allset); //清零
close(i);
continue;
}
printf("recv msg: %s", buffer);
send(i, buffer, 255, 0);
}
}
}
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: