使用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. OFDM、FTTx、SCTP、Ad Hoc、WSN术语简介

    上课提到一些术语,下来查了一下,总结在这里. OFDM: OFDM(Orthogonal Frequency Division Multiplexing)即正交频分复用技术,实际上OFDM是MCM(M ...

  2. GetForgroundWindow函数的不确定性——BUG笔记

    HWND GetForgoundWindows() 获取当前前置窗口在windows 7和windows 10下虚拟桌面切换后表现不同. 所以强烈不建议使用此函数!

  3. Windows 7桌面显示图标窗口句柄的获取

    在windows XP时代,我们获取桌面图标窗口的句柄往往用一下语句: HWND hwndParent = ::FindWindow( "Progman", "Progr ...

  4. dpdk快速编译使用

    QuickStart 环境 dpdk: dpdk-17.11 运行前配置 配置系统HugePages #mkdir /mnt/huge_1GB/ #vim /etc/fstab nodev /mnt/ ...

  5. JS动态添加元素的事件动态绑定

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  6. SQL语句新建数据库

    CREATE DATABASE 语句. CREATE DATABASE Epiphany ON ( NAME = Epiphany, FILENAME = 'E:\SQL SERVER 2008\Ep ...

  7. linux shell 搭建本地yum 源,通过IOS镜像 Centeros6,7还有redhat

    Centeros: 准备工作: 将系统镜像放到 /opt 下 脚本: #!/bin/bash mkdir /mnt/cdrom mount -o loop /opt/*.ios;# 此处改为你的系统镜 ...

  8. 企业级监控nagios实践

    nagios 监控服务应用指南 小区:视频监控,保安 企业工作中为什么要部署监控系统 监控系统相当于哨兵的作用,监控几百台上千台服务器,监控系统非常重要. 监控系统都需要监控 1. 本地资源:负载up ...

  9. Canal使用报错解决办法

    1. [destination = test_cancal , address = /127.0.0.1:3306 , EventParser] WARN c.a.o.s.a.i.setl.zooke ...

  10. C第10章-----通过引用传递

    #include <stdio.h> #include <math.h> void metersToFeetAndInches(double meters,unsigned i ...