我们先从select入手写一个模型,这是经过我们优化了的
#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include "wrap.h"
int main (void)
{
int i;
//max_fd的作用是每次在调用select时使用
int sock_main_fd,max_fd;
//我们自定义的文件描述符数组
int fd_array[1024];
//自定义文件描述符数组的指针
int p_array;
//监听集合,因为select中的参数是传入传出参数,所以我们需要两个,一个保存所有需要监听的文件描述符
fd_set all_set,new_set;
//正常创建socket的步骤
struct sockaddr_in addr;
sock_main_fd = Socket(AF_INET,SOCK_STREAM,0);
bzero((void*) &addr,sizeof(addr));
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(10000);
addr.sin_family = AF_INET;
Bind(sock_main_fd,(struct sockaddr *)&addr,sizeof(addr));
Listen(sock_main_fd,128);
//初始化最大文件描述符
max_fd = sock_main_fd;
//进行集合的初始化
FD_ZERO(&all_set);
//将sock_main_fd放入集合中
FD_SET(sock_main_fd,&all_set);
for(i = 0;i < 1024;i++)
{
fd_array[i] = -1;
}
p_array = -1;
while(1)
{
int i;
int sock_val;
int ready_num;
//将集合备份传递给new_set集合
new_set = all_set;
ready_num = select(max_fd + 1,&new_set,NULL,NULL,NULL);
//如果出错则退出
if(ready_num == -1)
{
perr_exit("select 函数错误");
}
//如果为true说明有连接请求,我们进行连接
if(FD_ISSET(sock_main_fd,&new_set))
{
int i;
//accept返回值
int link_fd;
int port;
char ip[100];
struct sockaddr_in addr;
socklen_t addr_len;
addr_len = sizeof(addr);
link_fd = Accept(sock_main_fd,(struct sockaddr*)&addr,&addr_len);
//打印监听到的连接的ip地址和端口号
inet_ntop(AF_INET,&addr.sin_addr.s_addr,ip,sizeof(ip));
port = ntohs(addr.sin_port);
//打印端口号和ip地址
printf("客户端的ip地址:%s 端口号:%d\r\n",ip,port);
//我们将其返回的文件描述符放入到我们自定义的数组当中去
for(i = 0;i < 1024;i++)
{
if(fd_array[i] == -1)
{
fd_array[i] = link_fd;
break;
}
}
//判断是否溢出
if(i == 1024)
{
perr_exit("自定义数组有溢出的危险");
}
//将连接的文件描述符放入监听集合中去
FD_SET(link_fd,& all_set);
//判断自定义数组指针是否需要移动
if(p_array < i)
{
p_array = i;
}
//判断当前的最大文件描述符个数
if(link_fd > max_fd)
{
max_fd = link_fd;
}
if((ready_num -- ) == 0)
{
continue;
}
}
//如果不是连接请求的话就是有读事件响应了
for(i = 0; i <= p_array;i++)
{
if((sock_val = fd_array[i]) == -1)
{
continue;
}
if(FD_ISSET(sock_val,&new_set))
{
char buf[1024];
int n;
//进行事件的读取操作
if( (n = Read(sock_val,buf,sizeof(buf))) == 0)
{
//清除监控集合中的值
FD_CLR(sock_val,&all_set);
//清除自定义数组中的值
fd_array[i] = -1;
//对读端进行关闭
Close(sock_val);
}
else if(n > 0){
char buf[1024];
for(i = 0; i < n ;i++)
{
buf[i] = toupper(buf[i]);
}
//像标准输出文件描述符输出
Write(STDOUT_FILENO,buf,n);
}
if((ready_num --) == 0)
{
continue;
}
}
}
}
Close(sock_main_fd);
exit(0);
}