世論調査のLinuxの高度なI / O機能とシンプルなサーバクライアントプログラミング

あなたは、同時に複数のファイルディスクリプタを監視する必要がある場合、それは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をリッスン

結果は:

server.bmp


おすすめ

転載: blog.51cto.com/zhaoxiaohu/2429580