//网络编程服务端
/*
* 备注:因为客户端代码、辅助方法代码和epoll相同,所以select只展示服务器端代码
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>//htons()函数头文件
#include <netinet/in.h>//inet_addr()头文件
#include <fcntl.h>
#include <sys/select.h>
#include <time.h>
#include "pub.h" #define MAXSOCKET 1024 int main(int arg, char *args[])
{
if (arg < )
{
printf("please print one param!\n");
return -;
}
//create server socket
int listen_st = server_socket(atoi(args[]));
if (listen_st < )
{
return -;
}
//设置非阻塞文件描述符
setnonblock(listen_st);
int i = ;
int maxfd = ; //最大的socket,select函数第一个参数使用
/*
*建立客户端连接池
*/
int client[MAXSOCKET]; //select最大支持1024个socket连接
//将所有的客户端连接池初始化,将每个成员都设置为-1,表示无效
for (; i < MAXSOCKET; i++)
{
client[i] = -;
}
maxfd = listen_st; //程序刚开始执行时,只有服务端socket,所以服务端socket最大
//定义一个事件数组结构
fd_set allset;
while ()
{
//初始化一个fd_set对象
FD_ZERO(&allset);
//将服务器端socket放入事件数组allset中(服务端socket需要特殊处理,所以没有放入socket池中)
FD_SET(listen_st, &allset);
//先假设最大的socket就是服务器端socket
maxfd = listen_st;
//遍历socket池 找出值最大的socket
for (i = ; i < MAXSOCKET; i++)
{
if (client[i] != -)
{
//将socket池中的所有socket都添加到事件数组allset中
FD_SET(client[i], &allset);
if (client[i] > maxfd)
{
maxfd = client[i]; //maxfd永远是值最大的socket
}
}
}
//开始等待socket发生读事件
int rc = select(maxfd + , &allset, NULL, NULL, NULL);
/*
* select函数返回之后,allset数组的数据产生变化,现在allset数组里的数据是发生事件的socket
* select和epoll不同,select每次返回后,
* 会清空select池中的所有socket,所有的socket等select返回后就被清除了
* 所以必须由程序建立一个socket池,每次都将socket池中的socket加入到select池中
* select不会为程序保存socket信息,这与epoll最大的不同,
* epoll添加到events中的socket,如果不是程序员清除,epoll永远保留这些socket
*/
if (rc < )
{
//select函数出错,跳出循环
printf("select failed ! error message:%s\n", strerror(errno));
break;
}
//判断是否是服务器socket接收到数据,有客户端连接
if (FD_ISSET(listen_st, &allset))
{
//accept
int client_st = server_accept(listen_st);
if (client_st < )
{
//直接跳出select循环
break;
}
//客户端连接成功 设置客户端非阻塞
setnonblock(client_st);
//将客户端socket加入socket池中
for (i = ; i < MAXSOCKET; i++)
{
if (client[i] == -)
{
client[i] = client_st;
break;
}
}
if (i == MAXSOCKET)
{
//socket池已满,关闭客户端连接
close_socket(client_st);
}
}
//处理客户端的socket
for (i = ; i < MAXSOCKET; i++)
{
if (client[i] == -)
{
//无效socket直接退出
continue;
}
//判断是否是这个socket有事件发生
if (FD_ISSET(client[i], &allset))
{
//接收消息
if (socket_recv(client[i]) < )
{
//如果接收消息出错,关闭客户端socket
close_socket(client[i]);
//从socket池中将这个socket清除
client[i] = -;
}
rc--;
}
//说明所有消息的socket已经处理完成
if (rc < )
{
//备注:双循环break只能跳出最近的一重循环
break;
}
}
}
//close server socket
close_socket(listen_st);
return ;
}

Linux 网络编程九(select应用--大并发处理)的更多相关文章

  1. linux网络编程九:splice函数,高效的零拷贝

    from:http://blog.csdn.net/jasonliuvip/article/details/22600569 linux网络编程九:splice函数,高效的零拷贝 最近在看<Li ...

  2. linux网络编程:select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET(转)

    从别人的博客中转载过来了这一篇文章,经过重新编辑排版之后展现于此,做一个知识点保存与学习. select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复 ...

  3. Linux 网络编程的5种IO模型:多路复用(select/poll/epoll)

    Linux 网络编程的5种IO模型:多路复用(select/poll/epoll) 背景 我们在上一讲 Linux 网络编程的5种IO模型:阻塞IO与非阻塞IO中,对于其中的 阻塞/非阻塞IO 进行了 ...

  4. Linux网络编程入门 (转载)

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

  5. [转] - Linux网络编程 -- 网络知识介绍

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

  6. 【转】Linux网络编程入门

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

  7. 《转》Linux网络编程入门

    原地址:http://www.cnblogs.com/duzouzhe/archive/2009/06/19/1506699.html (一)Linux网络编程--网络知识介绍 Linux网络编程-- ...

  8. Linux网络编程入门

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

  9. 【深入浅出Linux网络编程】 "开篇 -- 知其然,知其所以然"

    [深入浅出Linux网络编程]是一个连载博客,内容源于本人的工作经验,旨在给读者提供靠谱高效的学习途径,不必在零散的互联网资源中浪费精力,快速的掌握Linux网络编程. 连载包含4篇,会陆续编写发出, ...

随机推荐

  1. Spring(九)Spring对事务的支持

    一.对事务的支持 事务:是一组原子操作的工作单元,要么全部成功,要么全部失败 Spring管理事务方式: JDBC编程事务管理:--可以控制到代码中的行 可以清楚的控制事务的边界,事务控制粒度化细(编 ...

  2. SVN版本更新后,upData工程之后,Xcode 工程文件打不开解决办法

    svn更新代码后,打开xcode工程文件,会出现  xxx..xcodeproj  cannot be opened becausethe project file cannot be parsed. ...

  3. iOS之UI--转场动画

    1.什么是转场动画?    就是从一个场景转换到另一个场景,像导航控制器的push效果,就是一个转场.    2.如何创建转场动画    创建转场动画    CATransition *anim = ...

  4. <极客学院>视频教程学习笔记-iOS中CALayer的使用

    <1>CALayer简介 1.CALayer一般作为UIView的容器而使用. 2.CALayer是一个管理者图片载体(image-based content)的层结构 3.直接修改单独创 ...

  5. 通过设置虚拟机(ubantu15.10)的分辨率达到全屏效果

    最近搭建了一个ubantu 15.10虚拟机,怎么折腾都不能全屏显示.虽然我已经点了,  还是无法达到真正的全屏. 查了一下,http://jingyan.baidu.com/article/0964 ...

  6. 打印 SpringMVC中所有的接口URL

    采用junit test方式 1.配置  simple-test.xml  <?xml version="1.0" encoding="UTF-8"?&g ...

  7. I/O多路复用——select函数与poll函数

    1 区别 同:(1)机制类似,本质上没有多大差别,管理多个描述符也是进行轮询,根据描述符的状态进行处理.(2)包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间,而不论这些文件描述符是否就 ...

  8. 谈谈JavaScript的2种主要继承方式

    今天给自己巩固一下js的继承知识,基础不好,有不对的地方,请尽量拍砖,越重越好. js继承方法最主要的是2种,一种是通过原型的方式,一种是通过借用call&apply的构造函数方式. 1.原型 ...

  9. 怎么录制Android或IOS动画教程

    前一篇文章介绍了用DemoCreator制作Android视频教程,今天再介绍一种方法. 那就是用GifCam软件录制,此软件录制导出成Gif动画图片,可直接放在你的文章里面,效果比flash要好. ...

  10. Linux 下从头再走 GTK+-3.0 (六)

    在 GTK3 中增加了一个 GtkApplicaton 类,便于我们处理多窗口程序,同时有了 GtkApplication 我们也更容易创建灵活,易用,界面美观的应用程序. 在前面的几个例子中,演示了 ...