1. 程式人生 > >select函式例項程式碼

select函式例項程式碼

select函式簡解:
    selct 稱之為多路複用IO,使用它可以讓程式阻塞在select上,而非實際IO函式上.

    int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
             nfds: fd_set描述符集中 {最大描述符+1}
          readfds: 讀描述符集
         writefds: 寫描述符集
        exceptfds: 異常描述符集
          timeout: 超時時間,1)當timeout為NULL時,select
將阻塞到有讀或寫或異常描述符就緒才返回。 2)當timeout中tv_sec==0且tv_usec==0時,表示不等待,掃描一次馬上返回。 3)當timeout中tv_sec!=0且tv_usec!=0時,表示在指定時間內沒有就緒描述符就返回。函式返回0 注意: 1)正常情況下返回就緒描述符個數! 2)同時會將未就緒的描述符置零,所以select每次返回後我們都應將需用監聽的描述符重新新增到描述符集中。 3)為了可移植,當設定了超時時間時也應當從新賦值。 4
)使用select函式儘量不要與非系統IO混用 以下是對描述符集操作的函式: void FD_CLR(int fd, fd_set *set);
從描述符集set中清除描述符fd int FD_ISSET(int fd, fd_set *set); 判斷描述符fd 是否在描述符集set中,是,返回非0;否,返回0 void FD_SET(int fd, fd_set *set); 將描述符fd 新增到描述符集set中 void FD_ZERO(fd_set *set); 對描述符集進行清零,當我們新定義一個描述集時,最好使用此函式進行清零,
簡單的伺服器回射程式:

#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <strings.h>

#include "common.h"

#define SERV_PORT   10086

typedef struct sockaddr SA;

int main(void)
{
    int                 listenfd, connfd;
    struct sockaddr_in  cliaddr, servaddr;
    socklen_t           clientlen;


    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        err_quit("socket error");
    }

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family         =   AF_INET;
    servaddr.sin_port           =   htons(SERV_PORT);
    servaddr.sin_addr.s_addr    =   htonl(INADDR_ANY);

    if (bind(listenfd, (SA *)&servaddr, sizeof(servaddr)) < 0) {
        err_quit("bind error");
    }

    if (listen(listenfd, 5) < 0) {
        err_quit("listen error");
    }


    fd_set rfds, allfd;
    int maxfd, maxi = -1;

//method one:
    //int maxfd;
    //if ((maxfd = sysconf(_SC_OPEN_MAX)) < 0) {
    //  err_sys("sysconf error");
    //} 
    //
    //int clinet[maxfd];
//-----------------------------------------------------

//method two:
//在sys/select.h中定義了一個FD_SETSIZE其表示fd_set描述符總數。
    int client[FD_SETSIZE];
//-----------------------------------------------------

    int nready;
    int i, nread;
    int sockfd;
    char buf[MAXLINE];

    FD_ZERO(&allfd);
    FD_SET(listenfd, &allfd);
    maxfd = listenfd;

    for (i=0; i<FD_SETSIZE; ++i) {
        client[i] = -1;
    }


    for ( ; ; ) {

        rfds = allfd;

        nready = select(maxfd+1, &rfds, NULL, NULL, NULL);
        if (nready < 0) {
            err_quit("select error");
        }

        if (FD_ISSET(listenfd, &rfds)) {

#ifdef DEBUG
    printf("have descriptor....\n");
#endif

            clientlen = sizeof(cliaddr);
            connfd = accept(listenfd, (SA *)&cliaddr, &clientlen);
            if (connfd < 0) {
                err_quit("accept error");
            }

            for (i=0; i<FD_SETSIZE; ++i) {
                if (client[i] < 0) {
                    client[i] = connfd;
                    break;
                }
            }

            if (i == FD_SETSIZE) {
                err_quit("too many clients");
            }

            FD_SET(connfd, &allfd);

            if (connfd > maxfd) {
                maxfd = connfd;
            }

            if (i > maxi) {
                maxi = i;
            }

            if (--nready <= 0) {
                continue;
            }
        }

        for (i=0; i<=maxi; ++i) {
            if ((sockfd = client[i]) < 0) {
                continue;
            }

            if (FD_ISSET(sockfd, &rfds)) {

#ifdef  DEBUG
    printf("fd: %d\n", sockfd);
#endif

                if ((nread = read(sockfd, buf, MAXLINE)) == 0) {
                    close(sockfd);
                    FD_CLR(sockfd, &allfd);
                    client[i] = -1;
                } else {
                    if (write(sockfd, buf, nread) != nread) {
                        err_msg("fail to write...");
                    }
                }

                if (--nready <= 0) {
                    continue;
                }
            }
        }
    }

    return EXIT_SUCCESS;
}

相關推薦

select函式例項程式碼

select函式簡解: selct 稱之為多路複用IO,使用它可以讓程式阻塞在select上,而非實際IO函式上. int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *

生成32位數字(字母)函式例項程式碼

1. 生成32位數字(字母)函式 例項程式碼如下 function generateUUID() { var d = new Date().getTime();

Linux的select函式例項

/* 函式說明:正常每隔一秒列印一個數字,當有fd被設定時,就馬上執行操作。而不是被阻塞住 */ #include <sys/time.h> #include <sys/types.h> #include <unistd.h> #inclu

python函式程式碼複用,遞迴例項

Python函式的定義: 可選引數傳遞: 可變引數傳遞: 函式的返回值介紹: 全域性變數和區域性變數: 程式碼複用和函式遞迴:

c++ 模板函式,類模板,仿函式使用例項程式碼

1.模板函式  #include <iostream> using namespace std; template <class T> T myMin(T x, T y) { return (x < y) ? x : y; } void ma

有父類的子類例項化時,子類與父類的成員變數,建構函式程式碼塊的執行順序

package test; public class SuperC { static int i=10; SuperC(){ print(); } void print(){ System.out.println(i); } }package test; public class

例項程式碼理解一下c++11”定義解構函式阻止合成移動”

先普及一下基本知識: 1、移動:int &&a = b;  將b移動給a,會避免一些物件複製,移動之後,b就沒有用了。 2、析構:物件釋放時,執行的清理函式。 原理很好理解:如果定義了解構函式,則說明清理工作有一些個性化,成員資料如果執行了移動 ,會產生掃尾

socket程式設計select函式處理多個I/O併發

//本程式僅對客戶端進行處理多個併發的I/O //伺服器端 #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #

Java RMI特性及例項程式碼

RMI (Remote Method Invocation) 1,RMI 採用stubs 和 skeletons 來進行遠端物件(remote object)的通訊。stub 充當遠端物件的客戶端代理,有著和遠端物件相同的遠端介面,遠端物件的呼叫實際是通過呼叫該物件的客戶端代理物件stub來

通俗易懂的Adaboost演算法原理分析和例項+程式碼

   【尊重原創,轉載請註明出處】 http://blog.csdn.net/guyuealian/article/details/70995333     本人最初瞭解AdaBoost演算法著實是花了幾天時間,才明白他的基本原理。也許是自己能力有限吧,很多資

LwIP例項程式碼分析

//開發環境IAR int APP_Main(void) { #if C_USE_MCU_STM32F4xx  /* Ethernet configuration --------------------------------------*/ Ethernet_Initial(); w

Java IO 程式設計(BIO、NIO、AIO完整例項程式碼

      本文會從傳統的BIO到NIO再到AIO自淺至深介紹,並附上程式碼講解。   原始碼地址: https://github.com/kkman2008/java-IO.git     下面程式碼中會使用這樣一個

第三章棧作業題2-棧及其應用-計算機17級 6-1 爆記憶體函式例項 (6 分)

6-1 爆記憶體函式例項 (6 分) 本題要求實現一個遞迴函式,使用者傳入非負整型引數n,使用者依次輸出1到n之間的整數。所謂遞迴函式就是指自己呼叫自己的函式。 說明: (1)遞迴函式求解問題的基本思想是把一個大規模問題的求解歸結為一個相對較小規模問題的求解, 小規模

小程式實現上拉載入,例項程式碼

小程式實現上拉載入,例項程式碼 最近在做一個小程式,想實現下拉重新整理的功能,剛開始就遇到了一個尷尬的問題,原因是不認真o(╥﹏╥)o 下面是通過摸索總結出的步驟,給尋找問題的同伴提供參考: 下拉重新整理分為全域性和單頁面的: 全域性的設定就是在 app.js 中的 Windows

C#VS中一個函式呼叫另一個函式程式碼樣例

//主函式 說明:下面的函式是想求許可證的十六位編號,最後一位是許可編號的校驗碼,是以本體碼("JY" + xukbh)為基礎來計算 entities[0].XuKeZhengBianHao = "JY" + xukbh + xukebianhaojiaoyanma(xukbh);  

python-函式程式碼複用—七段數碼管繪製和愛心

import turtledef curvemove(): for i in range(200): turtle.right(1) turtle.forward(1)def drawGap(): turtle.penup() turtle.fd(5)def

java實現自定義異常例項程式碼

此處主要便於對異常類的使用上方便大家理解以一個公約數為例做了一個簡單自定義異常的處理程式碼如下: 如果操作者輸入數字符合要求程式執行,不符合則丟擲錯誤。 package 自定義異常簡單例項; import java.util.Scanner; public class CommonDivisor

JavaScript中立即執行函式例項詳解 轉載 作者:李牧羊

javascript和其他程式語言相比比較隨意,所以javascript程式碼中充滿各種奇葩的寫法,有時霧裡看花,當然,能理解各型各色的寫法也是對javascript語言特性更進一步的深入理解。這篇文章主要給大家介紹了關於JavaScript中立即執行函式的相關資料,需要的朋友可以參考下。 前言

TCP與UDP協議socket函式例項理解

socket 函式 int socket(int domain, int type, int protocol) 返回值: 非負描述符為成功,-1則出錯 domain: 指明的是網路層協議族/域,通常AF_INET、AF_INET6、AF_LOCAL等 type: 套介面型別

linux之select函式用法詳解

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!