링크 ux 네트워크 프로 그래 밍: epoll 의 인 스 턴 스
poll 을 개선 하 는 epoll 에 있어 서 프로 세 스 가 많은 socket 설명 자 를 여 는 것 을 지원 합 니 다. 즉, 이 컴퓨터 의 메모리 와 관계 가 있다 는 것 입 니 다!(일반 서버 는 다 커 요!)
다음은 나의 작은 PC 기기 의 표시 입 니 다.
pt@ubuntu:~$ cat /proc/sys/fs/file-max 391658 391658 개 에 이 르 렀 으 니 서버 로 서 는 분명, 헤헤 ~ ~ ~
epoll 의 기초 지식 을 인터넷 곳곳에서 찾 을 수 있 습 니 다. 바로 epoll 가 아 닙 니 다.creat 、epoll_ctl、epoll_wait 3 함수!다 들 뒤 져 봐. 나 도 공부 하고 있어...
이곳 은 주로 자신의 테스트 쓰레기 코드 를 붙 여 여러분 과 함께 격려 합 니 다!크 크 ~
읊다, 읊조리다
epoll_ctl epoll 의 이벤트 등록 함수 입 니 다. 이벤트 매개 변 수 는 다음 매크로 의 집합 일 수 있 습 니 다. EPOLLIN: 대응 하 는 파일 설명 자 를 읽 을 수 있 음 을 표시 합 니 다 (엔 드 SOCKET 의 정상 적 인 닫 기 포함). EPOLLOUT: 대응 하 는 파일 설명 자 를 표시 합 니 다. EPOLLPRI: 대응 하 는 파일 설명자 에 읽 을 수 있 는 긴급 한 데이터 가 있 음 을 표시 합 니 다. EPOLLERR: 대응 하 는 파일 설명자 에 오류 가 발생 했 음 을 표시 합 니 다.닫 힌 socket pipe broken EPOLLHUP: 대응 하 는 파일 설명자 가 끊 겼 음 을 표시 합 니 다.예 를 들 어 RST 가방 을 받 은 경우.이 이 벤트 를 등록 할 때 이 이 벤트 는 기본적으로 추 가 됩 니 다. EPOLLRdhup: 대응 하 는 파일 설명 자 를 나타 내 는 엔 드 socket 닫 기 이 벤트 는 주로 ET 모드 에 사 용 됩 니 다. 수평 트리거 모드 에서 엔 드 socket 이 닫 히 면 epollin 이벤트 가 계속 발생 하여 client socket 을 처리 합 니 다. 변두리 트리거 모드 에서 client 가 먼저 프로 토 콜 을 보 낸 다음 shutdown 쓰기 단 을 보 냅 니 다.epollin 이벤트 가 발생 합 니 다.그러나 처리 프로그램 이 recv 작업 을 한 번 만 할 때 recv 에서 받 은 데이터 길이 에 따라 뒤쪽 을 판독 합 니 다.
처리 해 야 할 프로 토 콜 이 있 는 지 여 부 는 클 라 이언 트 를 잃 어 버 리 고 이 벤트 를 닫 습 니 다. EPOLLET: EPOLL 을 가장자리 트리거 (Edge Triggered) 모드 로 설정 합 니 다. 이것 은 수평 트리거 (Level Triggered) 에 비해 말 합 니 다. EPOLLONESHOT: 사건 을 한 번 만 감청 합 니 다. 이번 사건 을 감청 한 후에 도 이 socket 을 계속 감청 해 야 한다 면 이 socket 을 다시 EPOLL 대기 열 에 넣 어야 합 니 다.
서버 쪽:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h> /* socket */
#include <sys/epoll.h> /* epoll */
#include <fcntl.h> /* nonblocking */
#include <sys/resource.h> /* setrlimit */
#define MAXEPOLL 10000 /* , ! */
#define MAXLINE 1024
#define PORT 6000
#define MAXBACK 1000
//!>
//!>
int setnonblocking( int fd )
{
if( fcntl( fd, F_SETFL, fcntl( fd, F_GETFD, 0 )|O_NONBLOCK ) == -1 )
{
printf("Set blocking error : %d
", errno);
return -1;
}
return 0;
}
int main( int argc, char ** argv )
{
int listen_fd;
int conn_fd;
int epoll_fd;
int nread;
int cur_fds; //!>
int wait_fds; //!> epoll_wait
int i;
struct sockaddr_in servaddr;
struct sockaddr_in cliaddr;
struct epoll_event ev;
struct epoll_event evs[MAXEPOLL];
struct rlimit rlt; //!>
char buf[MAXLINE];
socklen_t len = sizeof( struct sockaddr_in );
//!>
//!> , !
//!>
rlt.rlim_max = rlt.rlim_cur = MAXEPOLL;
if( setrlimit( RLIMIT_NOFILE, &rlt ) == -1 )
{
printf("Setrlimit Error : %d
", errno);
exit( EXIT_FAILURE );
}
//!> server
//!>
bzero( &servaddr, sizeof( servaddr ) );
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
servaddr.sin_port = htons( PORT );
//!>
if( ( listen_fd = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 )
{
printf("Socket Error...
" , errno );
exit( EXIT_FAILURE );
}
//!>
//!>
if( setnonblocking( listen_fd ) == -1 )
{
printf("Setnonblocking Error : %d
", errno);
exit( EXIT_FAILURE );
}
//!>
//!>
if( bind( listen_fd, ( struct sockaddr *)&servaddr, sizeof( struct sockaddr ) ) == -1 )
{
printf("Bind Error : %d
", errno);
exit( EXIT_FAILURE );
}
//!>
//!>
if( listen( listen_fd, MAXBACK ) == -1 )
{
printf("Listen Error : %d
", errno);
exit( EXIT_FAILURE );
}
//!> epoll
//!>
epoll_fd = epoll_create( MAXEPOLL ); //!> create
ev.events = EPOLLIN | EPOLLET; //!> accept Read!
ev.data.fd = listen_fd; //!> listen_fd
if( epoll_ctl( epoll_fd, EPOLL_CTL_ADD, listen_fd, &ev ) < 0 )
{
printf("Epoll Error : %d
", errno);
exit( EXIT_FAILURE );
}
cur_fds = 1;
while( 1 )
{
if( ( wait_fds = epoll_wait( epoll_fd, evs, cur_fds, -1 ) ) == -1 )
{
printf( "Epoll Wait Error : %d
", errno );
exit( EXIT_FAILURE );
}
for( i = 0; i < wait_fds; i++ )
{
if( evs[i].data.fd == listen_fd && cur_fds < MAXEPOLL )
//!> if
{
if( ( conn_fd = accept( listen_fd, (struct sockaddr *)&cliaddr, &len ) ) == -1 )
{
printf("Accept Error : %d
", errno);
exit( EXIT_FAILURE );
}
printf( "Server get from client !
"/*, inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port */);
ev.events = EPOLLIN | EPOLLET; //!> accept Read!
ev.data.fd = conn_fd; //!> conn_fd
if( epoll_ctl( epoll_fd, EPOLL_CTL_ADD, conn_fd, &ev ) < 0 )
{
printf("Epoll Error : %d
", errno);
exit( EXIT_FAILURE );
}
++cur_fds;
continue;
}
//!>
//!>
nread = read( evs[i].data.fd, buf, sizeof( buf ) );
if( nread <= 0 ) //!>
{
close( evs[i].data.fd );
epoll_ctl( epoll_fd, EPOLL_CTL_DEL, evs[i].data.fd, &ev ); //!> fd
--cur_fds; //!> !
continue;
}
write( evs[i].data.fd, buf, nread ); //!>
}
}
close( listen_fd );
return 0;
}
client:
본인 은 게 으 르 기 때문에 지난번 select 의 client 를 사용 하 세 요. 똑 같 습 니 다. 하하:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/select.h>
#define MAXLINE 1024
#define SERV_PORT 6000
//!> stdin, server
//!> client select
void send_and_recv( int connfd )
{
FILE * fp = stdin;
int lens;
char send[MAXLINE];
char recv[MAXLINE];
fd_set rset;
FD_ZERO( &rset );
int maxfd = ( fileno( fp ) > connfd ? fileno( fp ) : connfd + 1 );
//!>
int n;
while( 1 )
{
FD_SET( fileno( fp ), &rset );
FD_SET( connfd, &rset ); //!> rset
//!> ,
//!> ! !
if( select( maxfd, &rset, NULL, NULL, NULL ) == -1 )
{
printf("Client Select Error..
");
exit(EXIT_FAILURE );
}
//!> if
if( FD_ISSET( connfd, &rset ) ) //!> if
{
printf( "client get from server ...
" );
memset( recv, 0, sizeof( recv ) );
n = read( connfd, recv, MAXLINE );
if( n == 0 )
{
printf("Recv ok...
");
break;
}
else if( n == -1 )
{
printf("Recv error...
");
break;
}
else
{
lens = strlen( recv );
recv[lens] = '\0';
//!> stdout
write( STDOUT_FILENO, recv, MAXLINE );
printf("
");
}
}
//!> if stdin
if( FD_ISSET( fileno( fp ), &rset ) ) //!> if
{
//!> printf("client stdin ...
");
memset( send, 0, sizeof( send ) );
if( fgets( send, MAXLINE, fp ) == NULL )
{
printf("End...
");
exit( EXIT_FAILURE );
}
else
{
//!>if( str )
lens = strlen( send );
send[lens-1] = '\0'; //!>
//!> : !!!!!!!!
if( strcmp( send, "q" ) == 0 )
{
printf( "Bye..
" );
return;
}
printf("Client send : %s
", send);
write( connfd, send, strlen( send ) );
}
}
}
}
int main( int argc, char ** argv )
{
//!> char * SERV_IP = "10.30.97.188";
char buf[MAXLINE];
int connfd;
struct sockaddr_in servaddr;
if( argc != 2 )
{
printf("Input server ip !
");
exit( EXIT_FAILURE );
}
//!>
if( ( connfd = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 )
{
printf("Socket Error...
" , errno );
exit( EXIT_FAILURE );
}
//!>
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
//!> server
if( connect( connfd, ( struct sockaddr * )&servaddr, sizeof( servaddr ) ) < 0 )
{
printf("Connect error..
");
exit(EXIT_FAILURE);
}
/*else
{
printf("Connet ok..
");
}*/
//!>
//!> send and recv
send_and_recv( connfd );
//!>
close( connfd );
printf("Exit
");
return 0;
}
컴 파일 실행:
gcc -o server server.c
gcc -o client client.c
./server
./client
END
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Linux Shell 프로 그래 밍 - 텍스트 처리 grep, sed사용자 가 지정 한 '모드' 에 따라 대상 텍스트 를 일치 하 게 검사 하고 일치 하 는 줄 을 인쇄 합 니 다. ##포함 되 지 않 음, 역방향 일치 \ ##키워드 앞 뒤 가 맞지 않 고 키워드 만 일치 합 니 다...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.