Linux 서버 디자인 (1)
유 닉 스 네트워크 프로 그래 밍 의 4 가지 모델 은: prefork: 메 인 프로 세 스 accept
하위 프로 세 스 accept
prethread:
주 루틴 accept
서브 스 레 드 accept (우선 메 인 스 레 드 와 하위 스 레 드 로 설명 합 니 다)
첫 번 째 부분 은 '프 리 젠 테 이 션 프로 세 스' 로 처리 합 니 다.
CODE_1: server 는: 주 프로 세 스 accept 입 니 다. 그러면 이것 은 네 가지 방법 중 가장 복잡 합 니 다. 프로 세 스 간 에 socket 설명 자 를 전달 하 는 문제 와 관련 되 기 때 문 입 니 다!(프로 세 스 간 전달 설명 자 는 이전 bolg 에서 있 었 습 니 다!) server 는 폴 링 방식 으로 socket 을 하위 프로 세 스에 전달 합 니 다!
말 이 많 지 않 으 니 코드 를 붙 여 라.
Server:
/*
:
server , server pipe socket ,
server accept, , connfd pipe !
! server !!!
: select epoll, server listen msg, child
!
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <fcntl.h>
#define PORT 6000
#define MAXBACK 100
#define MAXLINE 1024
#define CHILD_NUM 10
typedef struct child_process
{
pid_t s_pid; //!> pid
int s_pipe_fd; //!> pipe
int s_status; //!> !0: 1:
}child_process;
child_process child[CHILD_NUM]; //!> 10 ( 10 )
static int n_child_use = 0; //!> child ( if )
//!> socket ( )
//!>
int send_fd( int fd_send_to, void * data, size_t len, int sock_fd )
{
struct msghdr msghdr_send; //!> the info struct
struct iovec iov[1]; //!> io vector
size_t n; //!>
union
{
struct cmsghdr cm; //!> control msg
char ctl[CMSG_SPACE(sizeof( int ))]; //!> the pointer of char
}ctl_un;
struct cmsghdr * pCmsghdr = NULL; //!> the pointer of control
msghdr_send.msg_control = ctl_un.ctl;
msghdr_send.msg_controllen = sizeof( ctl_un.ctl );
//!> design : the first info
pCmsghdr = CMSG_FIRSTHDR( &msghdr_send ); //!> the info of head
pCmsghdr->cmsg_len = CMSG_LEN(sizeof(int)); //!> the msg len
pCmsghdr->cmsg_level = SOL_SOCKET; //!> -> stream mode
pCmsghdr->cmsg_type = SCM_RIGHTS; //!> -> file descriptor
*((int *)CMSG_DATA( pCmsghdr )) = sock_fd; //!> data: the file fd
//!> these infos are nosignification
msghdr_send.msg_name = NULL; //!> the name
msghdr_send.msg_namelen = 0; //!> len of name
iov[0].iov_base = data; //!> no data here
iov[0].iov_len = len; //!> the len of data
msghdr_send.msg_iov = iov; //!> the io/vector info
msghdr_send.msg_iovlen = 1; //!> the num of iov
return ( sendmsg( fd_send_to, &msghdr_send, 0 ) ); //!> send msg now
}
//!> socket
//!>
int recv_sock_fd( int fd, void * data, size_t len, int * recv_fd )
{
struct msghdr msghdr_recv; //!> the info struct
struct iovec iov[1]; //!> io vector
size_t n; //!>
union
{
struct cmsghdr cm; //!> control msg
char ctl[CMSG_SPACE(sizeof( int ))]; //!> the pointer of char
}ctl_un;
struct cmsghdr * pCmsghdr = NULL; //!> the pointer of control
msghdr_recv.msg_control = ctl_un.ctl;
msghdr_recv.msg_controllen = sizeof( ctl_un.ctl );
//!> these infos are nosignification
msghdr_recv.msg_name = NULL; //!> the name
msghdr_recv.msg_namelen = 0; //!> len of name
iov[0].iov_base = data; //!> no data here
iov[0].iov_len = len; //!> the len of data
msghdr_recv.msg_iov = iov; //!> the io/vector info
msghdr_recv.msg_iovlen = 1; //!> the num of iov
if( ( n = recvmsg( fd, &msghdr_recv, 0 ) ) < 0 ) //!> recv msg
{ //!> the msg is recv by msghdr_recv
printf("recv error : %d
", errno);
exit(EXIT_FAILURE);
}
//!> now, we not use 'for' just because only one test_data_
if( ( pCmsghdr = CMSG_FIRSTHDR( &msghdr_recv ) ) != NULL //!> now we need only one,
&& pCmsghdr->cmsg_len == CMSG_LEN( sizeof( int ) ) //!> we should use 'for' when
) //!> there are many fds
{
if( pCmsghdr->cmsg_level != SOL_SOCKET )
{
printf("Ctl level should be SOL_SOCKET :%d
", errno);
exit(EXIT_FAILURE);
}
if( pCmsghdr->cmsg_type != SCM_RIGHTS )
{
printf("Ctl type should be SCM_RIGHTS : %d
", errno);
exit(EXIT_FAILURE);
}
*recv_fd =*((int*)CMSG_DATA(pCmsghdr)); //!> get the data : the file des*
}
else
{
*recv_fd = -1;
}
return n;
}
//!>
//!>
void web_child( int con_fd )
{
char buf[MAXLINE];
int n_read;
int i = 0;
while( strcmp( buf, "Q" ) != 0 && strcmp( buf, "q" ) != 0 )
{
memset( buf, 0, sizeof( buf ) );
if( ( n_read = read( conn_fd, buf, MAXLINE ) ) < 0 )
{
printf( "Read errnr! :%d
", errno );
exit( EXIT_FAILURE );
}
else if( n_read == 0 )
{
continue;
}
else
{
while( buf[i] )
{
buf[i] = toupper( buf[i] );
i++;
}
buf[i] = '\0';
printf("Child %d done!
", ( unsigned int )pthread_self());
printf("Child %d send %s
", ( unsigned int )pthread_self(), buf);
write( conn_fd, buf, strlen( buf ) ); //!> client
}
}
printf("Child %d : Dating end!
", ( unsigned int )pthread_self());
}
//!> child process
//!>
void child_main( int i )
{
char data; //!> socket, data ” “
int con_fd; //!> con_fd
int n_read; //!>
printf( "Child %d starting ...
", i );
while( 1 )
{
if( ( n_read = recv_sock_fd( STDERR_FILENO, &data, 1, &con_fd ) ) == 0 )
{
continue; //!> ,
//printf( " Child process %d read errnr! : %d
", i, errno );
//exit( EXIT_FAILURE );
}
if( con_fd < 0 )
{
printf("Child %d read connfd errnr! : %d
", i, errno);
exit( EXIT_FAILURE );
}
web_child( con_fd ); //!> child
write( STDERR_FILENO, " ", 1 ); //!> server , 0
}
}
//!>
//!>
void child_make( int i, int listen_fd )
{
int sock_fd[2]; //!> socket pair
pid_t pid;
//!> socketpair
if( socketpair( AF_LOCAL, SOCK_STREAM, 0, sock_fd ) == -1 )
{
printf( "create socketpair error : %d
", errno );
exit( EXIT_FAILURE );
}
if( ( pid = fork() ) > 0 ) //!>
{
close( sock_fd[1] );
child[i].s_pid = pid;
child[i].s_pipe_fd = sock_fd[0];
child[i].s_status = 0;
return;
}
if( dup2( sock_fd[0], STDERR_FILENO ) == -1 ) //!> STDERR_FILENO sock
{ //!> child STDERR_FILENO !
printf("socket pair errnr! : %d
", errno);
exit( EXIT_FAILURE );
}
close( sock_fd[0] ); //!> bu !
close( sock_fd[1] );
close( listen_fd );
child_main( i ); //!> child
}
//!> MAIN PROCESS
//!>
int main( int argc, char ** argv )
{
int i;
int listen_fd;
int conn_fd;
int max_fd;
int n_select;
int n_read;
char buf[5];
fd_set all_set, now_set;
struct sockaddr_in servaddr;
struct sockaddr_in cliaddr;
int len = sizeof( struct sockaddr_in );
//!> 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( bind( listen_fd, ( struct sockaddr *)&servaddr, sizeof( servaddr ) ) == -1 )
{
printf("Bind Error : %d
", errno);
exit( EXIT_FAILURE );
}
//!>
//!>
if( listen( listen_fd, MAXBACK ) == -1 )
{
printf("Listen Error : %d
", errno);
exit( EXIT_FAILURE );
}
FD_ZERO( &all_set );
FD_SET( listen_fd, &all_set ); //!> listenfd select
max_fd = listen_fd;
for( i = 0; i < CHILD_NUM; i++ )
{
child_make( i, listen_fd );
FD_SET( child[i].s_pipe_fd, &all_set ); //!> socket
max_fd = max_fd > child[i].s_pipe_fd ? max_fd : child[i].s_pipe_fd;
}
while( 1 ) //!>
{
now_set = all_set;
if( n_child_use >= CHILD_NUM ) //!> child
{ //!> listenfd , listen , child
FD_CLR( listen_fd, &now_set );
}
if( (n_select = select( max_fd + 1, &now_set, NULL, NULL, NULL )) == -1)
{
printf(" Main process select errnr~ :%d
", errno);
exit( EXIT_FAILURE );
}
if( FD_ISSET( listen_fd, &now_set ) ) //!> if
{
if( ( conn_fd = accept( listen_fd, ( struct sockaddr *)&cliaddr , &len ) ) == -1 )
{
printf("Server accept errnr! : %d
", errno);
exit( EXIT_FAILURE );
}
for( i = 0; i < CHILD_NUM; i++ )
{
if( child[i].s_status == 0 ) //!> child
{
break;
}
}
if( i == CHILD_NUM ) //!> child
{
printf("All childs are busy!
");
exit( EXIT_FAILURE ); //!> ,
}
child[i].s_status = 1; //!> busy
n_child_use++; //!> busy child ++
send_fd( child[i].s_pipe_fd, " ", 1, conn_fd ); //!> socket
close( conn_fd ); //!> server
if( --n_select == 0 ) //!>
{
continue;
}
}
for( i = 0; i < CHILD_NUM; i++ ) //!> child msg, server child
{
if( FD_ISSET( child[i].s_pipe_fd, &now_set ) )
{
if( ( n_read = read( child[i].s_pipe_fd, buf, 5 ) ) == 0 ) //!> buf data , child server
{
printf("Child %d exit error! : %d
", i, errno);
exit( EXIT_FAILURE );
}
child[i].s_status = 0; //!>
if( --n_select == 0 ) //!> if child for
{
break;
}
}
}
}
return 0;
}
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;
}
CODE_2: server 는 "하위 프로 세 스 accept" 입 니 다. 그러면 첫 번 째 보다 간단 합 니 다. 그러나 새로운 문 제 는 하위 프로 세 스 가 "accept" 를 빼 앗 으 려 면 반드시 "상호 배척" accept 문제 가 존재 합 니 다. 물론 저 희 는 파일 자 물 쇠 를 사용 할 수 있 지만 효율 이 낮 습 니 다. 그리고 여기 서 는 하나의 실험 일 뿐 이 므 로 "스 레 드 상호 배척 량" 을 사용 합 니 다.어 울 리 지 않 는 것 같 아, 흐흐 흐! ~
Server:
/*
:
server , accept,
,
!
, !
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/select.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <fcntl.h>
#define PORT 6000
#define MAXBACK 100
#define MAXLINE 1024
#define CHILD_NUM 10
pthread_mutex_t g_mutex; //!>
pthread_mutexattr_t g_mattr ; //!>
//!>
//!>
void child_make( int i_num, int listen_fd )
{
int i = 0;
pid_t pid;
int conn_fd;
int n_read;
char buf[MAXLINE];
struct sockaddr_in cliaddr;
int len = sizeof( struct sockaddr_in );
if( ( pid = fork() ) > 0 )
{
return;
}
while( 1 )
{
pthread_mutex_lock( &g_mutex ); //!>
if( ( conn_fd = accept( listen_fd, ( struct sockaddr *)&cliaddr , &len ) ) == -1 )
{
printf("Accept errnr! :%d
", errno);
exit( EXIT_FAILURE );
}
pthread_mutex_unlock( &g_mutex ); //!>
if( ( n_read = read( conn_fd, buf, MAXLINE ) ) < 0 )
{
printf( "Read errnr! :%d
", errno );
exit( EXIT_FAILURE );
}
else if( n_read == 0 )
{
continue;
}
else
{
while( buf[i] )
{
buf[i] = toupper( buf[i] );
i++;
}
printf("Child %d done!
", i_num);
printf("Child %d send %s
", i_num, buf);
write( conn_fd, buf, strlen( buf ) ); //!> client
}
}
}
//!> MAIN PROCESS
//!>
int main( int argc, char ** argv )
{
int i;
int listen_fd;
int conn_fd;
int n_read;
char buf[5];
struct sockaddr_in servaddr;
//!>
//!>
pthread_mutexattr_init( &g_mattr );
pthread_mutexattr_setpshared( &g_mattr, PTHREAD_PROCESS_SHARED );
pthread_mutex_init( &g_mutex, &g_mattr ); //!>
//!> 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( bind( listen_fd, ( struct sockaddr *)&servaddr, sizeof( servaddr ) ) == -1 )
{
printf("Bind Error : %d
", errno);
exit( EXIT_FAILURE );
}
//!>
//!>
if( listen( listen_fd, MAXBACK ) == -1 )
{
printf("Listen Error : %d
", errno);
exit( EXIT_FAILURE );
}
for( i = 0; i < CHILD_NUM; i++ )
{
child_make( i, listen_fd );
}
waitpid( 0 ); //!>
pthread_mutex_destroy( &g_mutex ); //!>
return 0;
}
Client: 위 에 거 랑 똑 같 아!!!
여기까지 프로 세 스 의 간단 한 처리 로 끝 났 습 니 다. 다음 편 은 스 레 드 처리 입 니 다 ~ ~
Bye~
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.