あなたは、同時に複数のファイルディスクリプタを監視する必要がある場合、それはI / Oの多重化機能が必要であり、I / Oの多重化機能は、ファイルディスクリプタをポーリングを選択している、ポーリング機能は、主に、今日使用されています。
世論調査では()のリスト構造「のstructたpollfd」へのポインタを受け取り、ポインタテストしたい含め、ファイルディスクリプタとイベントを。イベント・マスク・ビットは、構造内のイベントフィールドによって決定されます。現在の構造は、記入し、イベント後に呼び出しが返されます。
プロトタイプ:
書式#include <poll.h> int型世論調査(構造体たpollfd * FDS、nfds_t nfds個、int型のタイムアウト)。 構造体たpollfd { int型FD。/ *ファイルディスクリプタ* / 短いイベント。/ *要求されたイベント* / ショートにrevents; / *返されたイベント* / }
関数のパラメータ:FDS fdの配列をリッスンすることで、配列はnfds個、タイムアウトタイムアウト-1閉塞の数です。
言った機能:イベントの種類によって渡されたタイプは、同じのリターンかどうかを判断する場合局長に同じ関係。
イベント:
定数 |
説明 |
POLLIN |
通常または優先順位バンド可読データ |
POLLRDNORM |
通常のデータの読み出し |
POLLRDBAND |
優先バンド可読データ |
POLLPRI |
優先度の高いデータを読み出し可能 |
POLLOUT |
通常のデータを書き込むことができます |
POLLWRNORM |
通常のデータを書き込むことができます |
POLLWRBAND |
優先帯域データを書き込むことができます |
POLLERR |
エラーが発生しました |
POLLHUP |
ハングが発生します |
POLLNVAL |
記述子は、開いているファイルではありません |
次の例を聞いて2つのソケット・サーバーは、次のとおりです。
サーバーコード:
する#include <stdio.hに> する#include <STDLIB.H> の#include <string.hの> する#include <ERRNO.H> の#includeは<sys / types.h>に する#includeは<sys / socket.h>に する#include <netinetの/in.h> の#include <pthread.hの> 書式#include <unistd.h> の#include <poll.h> に#define MAX_POLLFD_NUM 2 //#はSERVER_CONN_IP1 "1.1.1.1"を定義 //#はSERVER_CONN_IP2 "1.1.1.1"を定義 #define DEFAULT_PORT 8000 の#define BUFF_MAX 1024 のtypedefボイド(* Server_Rrocess_Thread_Fun)(ボイド*の引数); / *スレッド処理機能は、* /定義 のtypedef構造体sever_thread_fun { Server_Rrocess_Thread_Fun Server_Process_Client_Conn1と、 / * / 1スレッド関数を接続 *空隙Poll_Conn1_Process(ボイド*引数) { unsigned char型ucBufArr [BUFF_MAX] = {0}。 符号なしlong ulSize = 0; int型のconnect_fd。 printf( "CONN1を\ n proessするpthreadのCONN1楽しい来ます"); ((connect_fd =(*(INT *)のarg、(いるsockaddr *)NULLを受け入れ、NULL))は== -1){場合 のprintf( "%sの(エラー番号:ソケットエラーを受け入れる%dを)"はstrerror(errnoに)、errnoに)。 } ulSize = RECV(connect_fd、ucBufArr、BUFF_MAX、0); もし((connect_fdを送って、 "!こんにちは、あなたは1に接続されている\ n"は、26.0)== -1) にperror( "エラーを送信します"); ucBufArr [ulSize] = '\ 0'; //スリープ(20)。 printf( "クライアントからのrecv MSG:%sの\ nを"、ucBufArr)。 クローズ(connect_fd)。 pthread_exit((ボイド*)1)。 } / * * / 1スレッド関数を接続 *空隙Poll_Conn2_Process(ボイド*の引数) { unsigned char型ucBufArr [BUFF_MAX] = {0}。 符号なしlong ulSize = 0; int型のconnect_fd。 printf( "conn2を\ n proessするpthreadのconn2楽しい来ます"); ((connect_fd =(*(INT *)のarg、(いるsockaddr *)NULLを受け入れ、NULL))は== -1){場合 のprintf( "%sの(エラー番号:ソケットエラーを受け入れる%dを)"はstrerror(errnoに)、errnoに)。 } ulSize = RECV(connect_fd、ucBufArr、BUFF_MAX、0); もし((connect_fdを送って、 "!こんにちは、あなたは2を接続している\ n"は、26.0)== -1) にperror( "エラーを送信します"); ucBufArr [ulSize] = '\ 0'; //スリープ(20)。 printf( "クライアントからのrecv MSG:%sの\ nを"、ucBufArr)。 クローズ(connect_fd)。 pthread_exit((ボイド*)2)。 } int型のmain() { int型poll_ret = 0。 がpthread_t thread_conn1; がpthread_t thread_conn2; / *ソケットVAR * / int型server_socket_fd_conn1。 int型のserver_socket_fd_conn2。 構造体のsockaddr_in servaddr_conn1。 構造体のsockaddr_in serveraddr_conn2。 / *ポーリングVAR * / 構造体たpollfd pollfd_arr [MAX_POLLFD_NUM]。 / * initは楽しい* /スレッド Poll_Server_Process_Clinet_FUN_tのserver_conn_handelを。 server_conn_handel.Server_Process_Client_Conn1 = Poll_Conn1_Process。 server_conn_handel.Server_Process_Client_Conn2 = Poll_Conn2_Process。 / *作成する2つのサーバーソケット* / IF((server_socket_fd_conn1 =ソケット(AF_INET、SOCK_STREAM、0))== -1){ printf( "ソケットCONN1エラー作成:%S(エラー番号:%d)は\ n"は、はstrerror(errnoに)、エラー番号を) 出口(0); } ((server_socket_fd_conn2 =ソケット(AF_INET、SOCK_STREAM、0))== -1)の場合{ のprintf( "ソケットconn2エラー作成:%S(エラー番号:%d)は\ n"は、はstrerror(errnoに)、エラー番号を) 出口(0); } / * INIT CONN1用ソケット1 * / memsetの(&servaddr_conn1、0、はsizeof(servaddr_conn1))。 servaddr_conn1.sin_family = AF_INET; servaddr_conn1.sin_addr.s_addr = htonl(INADDR_ANY)。 servaddr_conn1.sin_port = htons(DEFAULT_PORT)。 // IF(はinet_pton(AF_INET、SERVER_CONN_IP1、&servaddr_conn1.sin_addr.s_addr)<= 0){ // printfの( "%sの\ nのはinet_ptonエラー"、SERVER_CONN_IP1)。 //出口(0); memset(&serveraddr_conn2、0、はsizeof(serveraddr_conn2))。 serveraddr_conn2.sin_family = AF_INET; serveraddr_conn2.sin_addr.s_addr = htonl(INADDR_ANY)。 serveraddr_conn2.sin_port = htons(DEFAULT_PORT + 1)。 //(はinet_pton(AF_INET、SERVER_CONN_IP2、&serveraddr_conn2.sin_addr.s_addr)<= 0){もし //のprintf( "%sの\ nについてはinet_ptonエラー"、SERVER_CONN_IP2)。 //出口(0); //} / *バインド1つのソケットに接続* / IF(バインド(server_socket_fd_conn1、(構造体のsockaddr *)&servaddr_conn1、はsizeof(servaddr_conn1))== -1){ のprintf( "バインドソケットERROR1:%S(エラー番号:%d)は\ n」は、はstrerror(errnoに)、 出口(0); } / *バインド接続2ソケット* / IF(バインド(server_socket_fd_conn2、(構造体のsockaddr *)&serveraddr_conn2、はsizeof(serveraddr_conn2))== -1){ のprintf( "バインドソケットERROR2:%S(エラー番号:%d)は\ nは」はstrerror(errnoに)、errnoに)。 出口(0); } / * 1 * /接続聞く 場合((server_socket_fd_conn1、10聞く)== -1){ のprintf( "%sの(エラー番号:ソケットエラーを聴く%のD)\ n"は、はstrerror(errnoに)、エラー番号を) 出口(0); } * / / *聴く2を接続 ((server_socket_fd_conn2を聞く== -1)、10)場合、{ (、はstrerror(errnoに)、エラー番号"%d)は\ N:%S(errnoに待機ソケットエラー")のprintf 出口(0); } pollfd_arr [0] .events = POLLRDNORM; / *イベントのみを読み取ります* / pollfd_arr [0] .FD = server_socket_fd_conn1。 pollfd_arr [1] .events = POLLRDNORM; / *読み取り専用イベント* / pollfd_arr [1] .FD = server_socket_fd_conn2。 (1)一方、 { poll_ret =ポール(pollfd_arr、MAX_POLLFD_NUM、-1)。 (pollfd_arr [0] .revents&POLLRDNORM)なら 、{ / * * / 1プロセス・タスクを接続する のpthread_create()*(ボイドserver_conn_handel.Server_Process_Client_Conn1、(&pollfd_arr、NULL、&thread_conn1 [0] .FD))。 } (pollfd_arr [1] .revents&POLLRDNORM)なら 、{ / * * / 2プロセス・タスクを接続する のpthread_create(pollfd_arr&()*(ボイド、server_conn_handel.Server_Process_Client_Conn2、NULL、&thread_conn2 [1] .FD))。 } 睡眠(1)。 } 0を返します。 }
クライアントコード:
する#include <stdio.hに> する#include <STDLIB.H> の#include <string.hの> する#include <ERRNO.H> の#includeは<sys / types.h>に する#includeは<sys / socket.h>に する#include <netinetの/in.h> の#define BUFF_MAX 1024 の#define DEFAULT_PORT 8000 INTメイン(int型ARGC、チャー** ARGV) { int型数sockfd、N、rec_len。 チャーrecvline [BUFF_MAX]、[BUFF_MAX] sendline。 CHAR [BUFF_MAX] BUF。 構造体のsockaddr_in servaddr。 (!ARGC = 2){場合 のprintf( "用法:./client <IPアドレス> \ n"); 出口(0); } / *ソケットを作成する* / IF((数sockfd =ソケット(AF_INET、SOCK_STREAM、0))< %S(errnoに:( "ソケットエラーを作成するのprintf 出口(0); } のmemset(&servaddr、0、はsizeof(servaddr))。 servaddr.sin_family = AF_INET; servaddr.sin_port = htons(DEFAULT_PORT / * + 1 /); / * DEFAULT_PORTは、DEFAULT_PORT + 1 * /サーバに2を接続しているサーバーに1を接続している IP * / intに/ *文字列IP IF(はinet_pton(AF_INET、ARGV [ 1]、&servaddr.sin_addr)<= 0){ のprintf( "%sの\ nについてはinet_ptonエラー"、ARGV [1])。 出口(0); } / *接続サーバ* / {(数sockfd、(構造体のsockaddr *)&servaddr、はsizeof(servaddr))<0(接続)する場合 、 "エラー接続:%S(エラー番号:%d)は\ n"は(printf関数、はstrerror(errnoに)、errnoに)。 } のprintf( "サーバにMSGを送信:\ nを"); 関数fgets(sendline、BUFF_MAX、STDIN)。 数sockfd * /へ/ *書き込みデータ IF(送信(数sockfd、sendline、strlenを(sendline)、0)<0) { のprintf( "%sの(エラー番号:MSGエラー送信%のD)\ n"は、はstrerror(errnoに) 、エラー番号)。 出口(0); } / *読み取りソケットデータ* / IF((rec_len = RECV(数sockfd、BUF、BUFF_MAX、0))== -1){ perrorは( "RECVエラー")。 出口(1)。 } [rec_len] = '\ 0' BUF。 printf( "受信:%sのの\ nを"、bufが)。 / * colseソケット* / クローズ(数sockfd)。 出口(0); }
説明:サーバーのIP 127.0.0.1ポート8000とIP 127.0.0.1ポート8001をリッスン
結果は: