Linux 에서 Socket 기반 다 중 프로 세 스 실시 간 통신 실현

인터페이스 (Socket) 는 현재 리 눅 스에 서 가장 광범 위 하 게 사용 되 고 있 는 프로 세 스 간 통신 체제 로 다른 리 눅 스 통신 체제 와 다른 점 은 단일 컴퓨터 내 프로 세 스 간 통신 을 제외 하고 서로 다른 기계 간 의 프로 세 스 간 통신 에 도 사용 할 수 있다 는 점 이다.그러나 Socket 자체 가 대기 와 시간 초과 처 리 를 지원 하지 않 기 때문에 다 중 프로 세 스 간 의 상호 실시 간 통신 에 직접 사용 할 수 없습니다.
본 고 는 Socket 을 바탕 으로 하 는 다 중 프로 세 스 간 통신 의 실현 방법 을 제시 했다.원 리 는 통신 서버 (server) 로 각 프로 세 스 간 의 통신 을 전환 하 는 프로 세 스 를 만 드 는 것 이다.연결 요 구 를 감시 하 는 listening Socket 을 먼저 시작 하고 설명 (Descriptor) 번 호 를 미리 정 의 된 fd 에 추가 합 니 다.set 의 집합 중, 이 fdset 의 집합 은 listening Socket 과 나중에 생 성 된 통신 Socket 의 설명 번 호 를 저장 하 는 데 사 용 됩 니 다.서버 는 시스템 콜 select 를 사용 하여 이 집합 에 있 는 모든 socket 에 데이터 가 도 착 했 는 지 실시 간 으로 확인 합 니 다. 데이터 가 listening Socket 에 도착 하면 클 라 이언 트 가 시작 한 연결 요청 이 분명 합 니 다. 그래서 새로운 통신 Socket 을 생 성하 여 이 클 라 이언 트 와 연결 하고 생 성 된 Socket 설명 번 호 를 fd 에 추가 합 니 다.set 의 집합 에서 클 라 이언 트 의 ID 번호 와 이에 대응 하 는 Socket 의 설명 번 호 를 ID 등록 표 에 기록 합 니 다.만약 에 데이터 가 특정한 통신 Socket 에 도착 하면 이것 은 특정한 클 라 이언 트 가 제기 한 통신 요청 일 것 입 니 다. 데 이 터 를 읽 고 수신 클 라 이언 트 ID 번 호 를 꺼 내 고 ID 등록 표 에서 이에 대응 하 는 Socket 설명 번 호 를 찾 아 데 이 터 를 해당 하 는 Socket 을 통 해 수신 클 라 이언 트 로 전송 합 니 다.
다른 프로 세 스 는 클 라 이언 트 (client) 로 사 용 됩 니 다.클 라 이언 트 의 동작 은 먼저 통신 소켓 연결 서버 단 을 만 든 다음 통신 소켓 을 통 해 편 지 를 보 내 고 받 는 것 이다.
구체 적 인 절차 실현 과 설명 을 드 리 겠 습 니 다.
먼저 서버 엔 드 의 프로그램 을 보 여 줍 니 다. 여기 서 두 개의 클 라 이언 트 가 실시 간 으로 통신 할 것 이 라 고 가정 합 니 다. 클 라 이언 트 A 는 클 라 이언 트 B 에 문자 1 을 보 내 고 클 라 이언 트 B 는 클 라 이언 트 A 에 문자 2 를 보 냅 니 다.

  #include  <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <netinet/in.h>
int main()
{
  int        rcd ;
  struct sockaddr_un  server_sockaddr ;
  int        backlog ;
  ushort        ci ;
  int        watch_fd_list[3] ;
  fd_set        catch_fd_set ;
  fd_set        watchset ;
  int    new_cli_fd ;
  int   maxfd;
  int    socklen ,server_len;
  struct sockaddr_un  cli_sockaddr ;
  struct {
    char  module_id ;  /* Module ID    */
    int  cli_sock_fd ;  /* Socket ID    */
  } cli_info_t[2] ;
  
  for (ci=0;ci<=1;ci++)
    cli_info_t[ci].cli_sock_fd=-1;
    
  for (ci=0;ci<=2;ci++)
    watch_fd_list[ci]=-1;  
    
  int server_sockfd,client_sockfd;
  
  server_sockfd = socket( AF_UNIX, SOCK_STREAM, 0 ) ;
  server_sockaddr.sun_family = AF_UNIX ;
  strcpy( server_sockaddr.sun_path, "server_socket" ) ;
  server_len=sizeof(server_sockaddr);
  rcd = bind( server_sockfd, ( struct sockaddr * )&server_sockaddr, server_len ) ;
  
  backlog = 5 ;
  rcd = listen( server_sockfd, backlog ) ;
  printf("SERVER::Server is  waitting on socket=%d 
",server_sockfd); watch_fd_list[0]=server_sockfd; FD_ZERO( &watchset ) ; FD_SET( server_sockfd, &watchset ) ; maxfd=watch_fd_list[0];

 
위의 프로그램 에서 서버 는 listening Socket (server sockfd) 을 생 성하 고 Socket 감시 집합 (watchset) 을 초기 화하 고 listening Socket 을 Socket 감시 집합 에 넣 습 니 다.

			while (1){
		char ch;
		int fd;
		int nread;
		
		catch_fd_set=watchset;
		rcd = select( maxfd+1, &catch_fd_set, NULL, NULL, (struct timeval *)0 ) ;
		

 
위의 프로그램 에서 서버 는 시스템 호출 함수 select 를 사용 하여 Socket 감시 집합 에 데이터 가 있 는 지 실시 간 으로 확인 합 니 다.

        if ( rcd < 0 ) {
      printf("SERVER::Server 5 
"); exit(1); } if ( FD_ISSET( server_sockfd, &catch_fd_set ) ) { socklen = sizeof( cli_sockaddr ) ; new_cli_fd = accept( server_sockfd, ( struct sockaddr * ) &( cli_sockaddr ), &socklen ) ; printf(" SERVER::open communication with Client %s on socket %d
", cli_sockaddr.sun_path,new_cli_fd); for (ci=1;ci<=2;ci++){ if(watch_fd_list[ci] != -1) continue; else{ watch_fd_list[ci] = new_cli_fd; break; } } FD_SET(new_cli_fd , &watchset ) ; if ( maxfd < new_cli_fd ) { maxfd = new_cli_fd ; } for ( ci=0;ci<=1;ci++){ if(cli_info_t[ci].cli_sock_fd == -1) { cli_info_t[ci].module_id=cli_sockaddr.sun_path[0]; cli_info_t[ci].cli_sock_fd=new_cli_fd; break; } } continue; }

 
위의 프로그램 에서 서버 는 시스템 호출 함수 FD 를 사용 합 니 다.ISSET 는 클 라 이언 트 의 연결 요청 이 Listening Socket 에 도 착 했 는 지 확인 합 니 다. 반환 값 이 0 이상 이면 서버 는 새로운 통신 Socket (new cli fd) 을 생 성하 여 클 라 이언 트 와 연결 합 니 다.새로 생 성 된 통신 소켓 을 소켓 감시 집합 (FD SET) 에 넣 습 니 다.클 라 이언 트 의 정보 (ID 번호 와 Socket 설명 번호) 를 레 지 스 트 cli 에 저장 합 니 다.info_t 중

    for ( ci = 1; ci<=2 ; ci++ ) {
      int      dst_fd = -1 ;
      char      dst_module_id;
      char       src_module_id;
      int    i;
      if (watch_fd_list[ ci ]==-1) continue;
      if ( !FD_ISSET( watch_fd_list[ ci ], &catch_fd_set ) ) {
        continue ;
      }
      ioctl(watch_fd_list[ ci ],FIONREAD,&nread);
      if (nread==0){
        continue;
      }  
      read( watch_fd_list[ ci ], &dst_module_id, 1 ) ;
      for (i=0;i<=1;i++){
        if(cli_info_t[i].module_id == dst_module_id) 
          dst_fd=  cli_info_t[i].cli_sock_fd;  
         if(cli_info_t[i].cli_sock_fd==watch_fd_list[ ci ]) 
        src_module_id=  cli_info_t[i].module_id;    
      }
      read( watch_fd_list[ ci ], &ch, 1 ) ;
      printf("SERVER::char=%c to  Client %c on socket%d
",ch, dst_module_id,dst_fd); write(dst_fd,&src_module_id, 1 ) ; write(dst_fd,&ch, 1 ) ; } } }

 
위의 프로그램 에서 어떤 통신 Socket 에 데이터 가 도착 하면 Server 는 데 이 터 를 읽 고 수신 클 라 이언 트 ID 번 호 를 꺼 냅 니 다.ID 등록 표 에서 수신 클 라 이언 트 에 대응 하 는 Socket 설명 번 호 를 찾 습 니 다.그리고 데 이 터 를 대응 하 는 Socket 을 통 해 수신 클 라 이언 트 로 전송 합 니 다.
클 라 이언 트 클 라 이언 트 A 를 위 한 프로그램
Client B 프로그램 은 char dstmodule_id='B'; char dst 로 변경module_id='A'; char ch='1'; char char ch = '2' 로 변경 하기;기왕에.

#include  <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(){
	
	int client_sockfd;
	int len;
	struct sockaddr_un server_sockaddr,cli_sockaddr;
	int result;
	char dst_module_id='B';
	char ch='1';
	char src_module_id;
	
	
	client_sockfd= socket(AF_UNIX,SOCK_STREAM,0);
	
	cli_sockaddr.sun_family = AF_UNIX ;
	strcpy( cli_sockaddr.sun_path, "A" ) ;
	bind(client_sockfd,(struct sockaddr * )&cli_sockaddr, sizeof( cli_sockaddr ) ) ;
	server_sockaddr.sun_family=AF_UNIX;
	strcpy( server_sockaddr.sun_path, "server_socket" ) ;
	len=sizeof(server_sockaddr);
	
	result = connect(client_sockfd,( struct sockaddr * )&server_sockaddr,len);
	if (result <0){
		printf("ClientA::error on connecting 
"); exit(1); } printf("ClientA::succeed in connecting with server
"); sleep(10); write(client_sockfd,&dst_module_id,1); write(client_sockfd,&ch,1); read (client_sockfd,&src_module_id,1); read (client_sockfd,&ch,1); printf("ClientA::char from Client %c =%c
", src_module_id,ch); close (client_sockfd); }

 
다음은 샘플 프로그램의 실행 결과 입 니 다.

[root@zhou test]# ./server &
[3] 4301
[root@zhou test]# SERVER::Server is  waitting on socket=3
./clientA & ./clientB &
[4] 4302
[5] 4303
ClientA::succeed in connecting with server
 SERVER::open communication with  Client A on socket 4
[root@zhou test]#  SERVER::open communication with  Client B on socket 5
ClientB::succeed in connecting with server
SERVER::char=1 to  Client B on socket5
ClientB::char from  Client A =1
SERVER::char=2 to  Client A on socket4
ClientA::char from  Client B =2

좋은 웹페이지 즐겨찾기