使用select函数可以以非阻塞的方式和多个socket通信。程序只是演示select函数的使用,功能非常简单,即使某个连接关闭以后也不会修改当前连接数,连接数达到最大值后会终止程序。

1. 程序使用了一个数组fd_A,通信开始后把需要通信的多个socket描述符都放入此数组。

2. 首先生成一个叫sock_fd的socket描述符,用于监听端口。

3. 将sock_fd和数组fd_A中不为0的描述符放入select将检查的集合fdsr。

4. 处理fdsr中可以接收数据的连接。如果是sock_fd,表明有新连接加入,将新加入连接的socket描述符放置到fd_A。

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <errno.h>

#include <string.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#define MYPORT 1234    // the port users will be connecting to

#define BACKLOG 5     // how many pending connections queue will hold

#define BUF_SIZE 200

int fd_A[BACKLOG];    // accepted connection fd

int conn_amount;    // current connection amount

void showclient()

{

int i;

printf("client amount: %d\n", conn_amount);

for (i = 0; i < BACKLOG; i++) {

printf("[%d]:%d  ", i, fd_A[i]);

}

printf("\n\n");

}

int main(void)

{

int sock_fd, new_fd;  // listen on sock_fd, new connection on new_fd

struct sockaddr_in server_addr;    // server address information

struct sockaddr_in client_addr; // connector's address information

socklen_t sin_size;

int yes = 1;

char buf[BUF_SIZE];

int ret;

int i;

if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {

perror("socket");

exit(1);

}

if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {

perror("setsockopt");

exit(1);

}

server_addr.sin_family = AF_INET;         // host byte order

server_addr.sin_port = htons(MYPORT);     // short, network byte order

server_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP

memset(server_addr.sin_zero, '\0', sizeof(server_addr.sin_zero));

if (bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {

perror("bind");

exit(1);

}

if (listen(sock_fd, BACKLOG) == -1) {

perror("listen");

exit(1);

}

printf("listen port %d\n", MYPORT);

fd_set fdsr;

int maxsock;

struct timeval tv;

conn_amount = 0;

sin_size = sizeof(client_addr);

maxsock = sock_fd;

while (1) {

// initialize file descriptor set

FD_ZERO(&fdsr);

FD_SET(sock_fd, &fdsr);

// timeout setting

tv.tv_sec = 30;

tv.tv_usec = 0;

// add active connection to fd set

for (i = 0; i < BACKLOG; i++) {

if (fd_A[i] != 0) {

FD_SET(fd_A[i], &fdsr);

}

}

ret = select(maxsock + 1, &fdsr, NULL, NULL, &tv);

if (ret < 0) {

perror("select");

break;

} else if (ret == 0) {

printf("timeout\n");

continue;

}

// check every fd in the set

for (i = 0; i < conn_amount; i++) {

if (FD_ISSET(fd_A[i], &fdsr)) {

ret = recv(fd_A[i], buf, sizeof(buf), 0);

if (ret <= 0) {        // client close

printf("client[%d] close\n", i);

close(fd_A[i]);

FD_CLR(fd_A[i], &fdsr);

fd_A[i] = 0;

} else {        // receive data

if (ret < BUF_SIZE)

memset(&buf[ret], '\0', 1);

printf("client[%d] send:%s\n", i, buf);

}

}

}

// check whether a new connection comes

if (FD_ISSET(sock_fd, &fdsr)) {

new_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size);

if (new_fd <= 0) {

perror("accept");

continue;

}

// add to fd queue

if (conn_amount < BACKLOG) {

fd_A[conn_amount++] = new_fd;

printf("new connection client[%d] %s:%d\n", conn_amount,

inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

if (new_fd > maxsock)

maxsock = new_fd;

}

else {

printf("max connections arrive, exit\n");

send(new_fd, "bye", 4, 0);

close(new_fd);

break;

}

}

showclient();

}

// close other connections

for (i = 0; i < BACKLOG; i++) {

if (fd_A[i] != 0) {

close(fd_A[i]);

}

}

exit(0);

}

转 linux socket的select函数例子的更多相关文章

  1. linux c语言 select函数用法

    linux c语言 select函数用法 表头文件 #i nclude<sys/time.h> #i nclude<sys/types.h> #i nclude<unis ...

  2. linux c语言 select函数使用方法

    linux c语言 select函数使用方法 表头文件 #i nclude<sys/time.h> #i nclude<sys/types.h> #i nclude<un ...

  3. linux 下的select函数

    函数原型 /* According to POSIX.1-2001 */ #include <sys/select.h>  //头文件 /* According to earlier st ...

  4. linux select函数:Linux下select函数的使用详解【转】

    本文转载自;http://www.bkjia.com/article/28216.html Linux下select函数的使用 Linux下select函数的使用 一.Select 函数详细介绍 Se ...

  5. linux c中select使用方法

    1.select函数作为定时器使用    it_value.tv_sec = 0;    it_value.tv_usec = 100000:    select(1,NULL,NULL,NULL,& ...

  6. select()函数用法二

    Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如 connect.accept.recv或recvfrom这样的阻塞程序 ...

  7. linux c中select使用技巧

    1.select函数作为定时器使用    it_value.tv_sec = 0;    it_value.tv_usec = 100000:    select(1,NULL,NULL,NULL,& ...

  8. Linux下select函数的使用

    一.Select 函数详细介绍 Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect. accept.recv ...

  9. linux select函数详解

    linux select函数详解 在Linux中,我们可以使用select函数实现I/O端口的复用,传递给 select函数的参数会告诉内核: •我们所关心的文件描述符 •对每个描述符,我们所关心的状 ...

随机推荐

  1. 【人工智能系列】python的Quepy库的学习

    第一篇 了解 什么是Quepy quepy是一个Python框架改造自然语言问题在数据库查询语言查询.它可以很容易地定制不同类型的问题,在自然语言和数据库查询.因此,用很少的代码,你可以建立自己的系统 ...

  2. 云梯互联:所有主机已全面支持免费SSL!附小白配置教程。

    HTTPS和HTTP的区别:1.HTTPS是加密传输协议,HTTP是名文传输协议;2.HTTPS需要用到SSL证书,而HTTP不用;3.HTTPS比HTTP更加安全,对搜索引擎更友好,利于SEO4. ...

  3. DROP VIEW - 删除一个视图

    SYNOPSIS DROP VIEW name [, ...] [ CASCADE | RESTRICT ] DESCRIPTION 描述 DROP VIEW 从数据库中删除一个现存的视图. 执行这条 ...

  4. 【整理】treeGrid 树形表格

    treeGrid 树形表格 https://fly.layui.com/extend/treeGrid/

  5. python之range (范围)

    例题: for i in range(10): print(i,end='') # 输出结果 0123456789 # s = range(1,10) # 面试大坑 python2 和 python3 ...

  6. MFC隐藏在黑暗之中的大坑

    大坑一:CDC会随着窗口状态的改变而改变 void K5::OnPaint() { CDC *pDC=this->GetDC(); //CDC最好设为局部变量 ... this->Rele ...

  7. ios7与ios6UI风格区别

    http://apple.xdnice.com/content/applenews/2013/0614/142195.html         (ios7 ui风格) http://blog.csdn ...

  8. Shading-jdbc源码分析-sql词法解析

    前言 前有芋艿大佬已经发过相关分析的文章,自己觉的源码总归要看一下,然后看了就要记录下来(记性很差...),所以就有了这篇文章(以后还要继续更

  9. 14. PARAMETERS

    14. PARAMETERS PARAMETERS表提供有关存储例程(存储过程和存储函数)的参数以及存储函数的返回值的信息. PARAMETERS表不包含内置SQL函数或用户定义函数(UDF). 参数 ...

  10. 配置github SSH公钥登录

    git的安装见https://www.cnblogs.com/liliyang/p/9829931.html 配置git使用ssh密钥 git支持https和git两种传输协议,github分享链接时 ...