//网络编程服务端
/*
* 备注:因为客户端代码、辅助方法代码和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. Hibernate框架的基本搭建(一个小的java project的测试向数据库中插入和查询数据的功能)

    Hibernate介绍:Hibernate是一种“对象-关系型数据映射组件”,它使用映射文件将对象(object)与关系型数据(Relational)相关联,在Hibernate中映射文件通常以&qu ...

  2. Git使用之设置SSH Key

    设置SSH Key 1.    检查是否已经有SSH Key. $cd ~/.ssh 如果说没有这个目录,就直接看第三步 2.    备份 3.    生成一个新的SSH. $ssh-keygen - ...

  3. android 隐藏标题栏

    在onCreate()方法中添加如下代码: public class FirstActivity extends Activity { @Override protected void onCreat ...

  4. IOS开发--待研究源码(持续添加更新)

    1.丰富的CAEmitterLayer制作的粒子效果,比如烟花效果 (还未研究) 该项目本人未研究,待以后有时间或者有需求再研究 github源码下载地址:https://github.com/lic ...

  5. XCode中#pragma的使用

    为了能够快速定位到代码的目标位置,可以使用#pragma:  

  6. C# Process运行cmd命令的异步回显

    以下的代码为new Process() 调用cmd命令,并将结果异步回显到Form的例子: 以下的代码为new Process() 调用cmd命令,并将结果异步回显到Form的例子: [csharp] ...

  7. Spring配置文件外部化配置及.properties的通用方法

    摘要:本文深入探讨了配置化文件(即.properties)的普遍应用方式.包括了Spring.一般的.远程的三种使用方案. 关键词:.properties, Spring, Disconf, Java ...

  8. 烂泥:【解决】word复制windows live writer没有图片

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 在使用windows live writer发表博客,博客先是在是word2013中进行编辑,编辑完毕后我会复制到windows live writer ...

  9. UWP 矢量字体图标(iconfont)使用

    本文使用 阿里巴巴开源字体: 选择矢量字体图标: 查看或编辑 Unicode编码 或字体名称 下载到本地,添加到uwp项目 代码中写法 Text:Unicode编码 FontFamily:文件路径#字 ...

  10. Sample SecondarySort 浅析

    示例文件: 100 99 100 98 100 56 100 78 20 100 30 100 20 50 30 50 30 60 20 80 需求:首先按第一个数字分组,组成按第二个数字排序. 解决 ...