본문 바로가기
코스웨어/11년 내장형하드웨어

[내장형]이상만 7월 26일 일일보고서

by 알 수 없는 사용자 2011. 7. 26.
728x90
반응형

오늘 수업시간에는 채팅프로그램을 제작하는 시간을 가졌습니다

어제 소스를 분석하지 않고 넘어가서 분석을 한번 해보도록 하겠습니다

본격!! 시키지도 않았는데 열심히 분석하는...ㅋㅋ

=[echo_server_sel.c
소스예제]=

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define BUFSIZE 100
void error_handling(char *message);

int main(int argc, char *argv[])
{
  int serv_sock;
  struct sockaddr_in serv_addr;

  fd_set reads, temps;
  int fd_max;

  char message[BUFSIZE];
  int str_len;
  struct timeval timeout;

  if(argc != 2)
  {
    printf("Usage: %s PortNum \n", argv[0]);
    exit(1);
  }

  serv_sock = socket(PF_INET, SOCK_STREAM, 0);

  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  serv_addr.sin_port = htons(atoi(argv[1]));

  if( bind(serv_sock, (struct sockaddr *)&serv_addr,sizeof(serv_addr)))
    error_handling("bind() error");

  if(listen(serv_sock,5== -1)
      error_handling("listen() error");

  FD_ZERO(&reads);
  FD_SET(serv_sock, &reads);
  fd_max = serv_sock;

  while(1)
  {
    int fd, str_len;
    int clnt_sock, clnt_len;
    struct sockaddr_in clnt_addr;

    temps = reads;

    timeout.tv_sec = 5;
    timeout.tv_usec = 0;

    if(select(fd_max+1&temps,0,0&timeout) == -1)
      error_handling("select() error");

    for(fd=0;fd<fd_max+1;fd++)
    {
       if(FD_ISSET(fd, &temps))
      {
        if(fd == serv_sock)
        {
          clnt_len = sizeof(clnt_addr);
          clnt_sock = accept(serv_sock,(struct sockaddr *)&clnt_addr, &clnt_len);

          FD_SET(clnt_sock, &reads); //read
 clnt_sock등록
          if(fd_max<clnt_sock)
            fd_max = clnt_sock;//
개수 갱신

          printf("client 
접속 : 소켓 디스크립터 %d \n", clnt_sock);
        }
        else //clnt_sock
 변화가 있는 경우
        {
          str_len = read(fd, message, BUFSIZE);
          if(str_len == 0)//
연결 종료 요청인 경우
          {
            FD_CLR(fd, &reads);
            close(fd);
            printf("client 
종료 : 소켓디스크립터 %d \n", fd);
          }
          else
          {
            write(fd, message, str_len);
          }
        }
      }
    }
  }
  return 0;
}

void error_handling(char *message)
{
  fputs(message,stderr);
  fputc('\0',stderr);
  exit(1);
}

 

echo_server_sel소스를 순서대로 분석을 해보겠습니다 실제 프로그램이 실행되는 동안에 어떤값이 들어있고 어떤순서로 진행되는지 제대로 (제가)파악을 못하고 있는 것 같아서 해보게 되었습니다 혹시나 잘못 이해하고 있는 부분이 있다면 지적하여 주세요~!!


프로그램이 실행되는 순서대로 한번 따라가 보겠습니다
 

참고>>select()함수에 필요한 헤더파일

#include <unistd.h>
#include <sys/types.h>

 

다음으로 main함수로 들어가겠습니다

 

  fd_set reads, temps;
  int fd_max;
  struct timeval timeout;

 

변수가 선언되어 있습니다

select함수를 사용하기 위해서 fd_set reads와 원본값을 들고 있기 위한 temps 그리고 파이디스크립터 검사 범위설정을 위하여 fd_max를 선언해두었습니다 그리고 시간을 식별하기 위한 timeval구조체가 선언되어있습니다

 

serv_sock = socket(PF_INET, SOCK_STREAM, 0);

 

조금 더 내려가면 main의 인자 값을 체크하고 있고 거기서 조금더 내려가면 sock초기화가 나옵니다 socket 반환값을 알고 싶어서 printf(%d\n, serv_sock); 해보니 3라는 값을 알 수 있었습니다

 

bind listen을 하고 나면 FD값의 초기화가 나옵니다 초기화가 되어지는 순서를 그림으로 표현하면 다음과 같습니다

 

FD_ZERO(&reads);

fd0

fd1

fd2

fd3

fd4

......

0

0

0

0

0

......


  

 

FD_SET(serv_sock, &reads);

fd0

fd1

fd2

fd3

fd4

......

0

0

0

1

0

......

 

 


  fd_max = serv_sock;

 

그리고 fd_max에는 3을 가지고 있습니다

 

  while(1)
  {
    int fd, str_len;
    int clnt_sock, clnt_len;
    struct sockaddr_in clnt_addr;

    temps = reads;

while문은 항상 참으로 무한으로 반복합니다 클라이언트 소켓과 관련된 변수를 선언해주고 앞에서 읽었던 reads temps에 넣어 초기화를 시켜줍니다 그럼 temps의 값은

fd0

fd1

fd2

fd3

fd4

......

0

0

0

1

0

......

 

 

 

이 됩니다~~

 

    timeout.tv_sec = 5;
    timeout.tv_usec = 0;

 

_sec는 초를 뜻하는 단위이고 _usec 마이로 세컨드를 뜻하는 단위입니다 5,0 이란 말은 5초동안을 뜻합니다 _usec에 값을 넣으면 _sec시간과 합쳐진 만큼 동작시간을 가지게 됩니다 즉 마이크로 세컨드가 백만분의 1초이니 여기다 백만을 넣고 _sec 5를 넣으면 6초간 이라는 의미가 됩니다

 

if(select(fd_max+1&temps,0,0&timeout) == -1)

fd0

fd1

fd2

fd3

fd4

......

0

0

0

1

0

......

 

 

 

select함수는 (검색 대상이되는 파일디스크립터수, 읽기, 쓰기, 오류, 시간)을 담고 있는데 현제 fd_max 1을 더한 만큼 범위를 설정하면 계산할 범위를 설정할수있습니다 fd_mac3이니 +1하면 4가 되어있습니다 -1은 오류를 뜻하니 오류가 발생하지 않아서 아래로 내려갑니다 정확하게 이야기하자면 5초동안 대기한후 아래로 내려갑니다 

 

    for(fd=0;fd<fd_max+1;fd++)
    {
      if(FD_ISSET(fd, &temps))
      {

  

이제 for문에서 fd0부터 fd_max+1한 만큼 범위를 검사합니다 그래서 FD_ISSET으로 값이 발견되면 if문 안으로 들어가게 됩니다 현제 fd 4일때 if문 안으로 들어갑니다

 

        if(fd == serv_sock)
        {
          clnt_len = sizeof(clnt_addr);
          clnt_sock = accept(serv_sock,(struct sockaddr *)&clnt_addr, &clnt_len);

여기까지 진행하고 accept를 시켜주지 않으면 5초후 다시 반복하게 됩니다printf문으로 출력해보니 fd값이 if문안에서 3까지 증가(0,1,2,3)하는 것을 확인할 수있었습니다 client의 연결이 허락된 후에는 clnt_sock에는 4라는 값이 들어오게됩니다

 

FD_SET(clnt_sock, &reads); //read clnt_sock등록

fd0

fd1

fd2

fd3

fd4

......

0

0

0

0

1

......

 

 

 

fd4 clnt_sock으로 세팅을 하였습니다

 

if(fd_max<clnt_sock)
            fd_max = clnt_sock;//
개수 갱신

현재 fd_max while문 밖에서 3이라는 값을 가지고 왔고 clnt_sock 4라는 값을 가지고 있기 때문에 if(3<4)참이 됩니다 fd_max값이 이제는 clnt_sock 값으로 초기화되게 됩니다. printf fd를 돌려보니 0,1,2,3 으로 증가하다 client접속후에는 0,1,2,3,4까지 증가하는 것을 확인 할 수 있었습니다

 

        else //clnt_sock 변화가 있는 경우
        {
          str_len = read(fd, message, BUFSIZE);

 

앞에서 clnt의 변화가 있었기 때문에 현재 연결되어 있는 상태입니다 read에 와서 block되어 있는 상태 입니다 client에서 접속을 끝게되면 EOF 0을 반환하게 되어 종료하게 됩니다

 

        if(str_len == 0)//연결 종료 요청인 경우
          {
            FD_CLR(fd, &reads);
            close(fd);
            printf("client 
종료 : 소켓디스크립터 %d \n", fd);
          }

 

종료하면서 fd가 가리키는 곳을 0으로 클릭어 하게됩니다

fd0

fd1

fd2

fd3

fd4

......

0

0

0

0

0

......

 

 

 

          else
          {
            write(fd, message, str_len);
          }

종료가 아닐경우 else문으로 들어가 읽어드린 message를 쓰고 있습니다

 

그리고 다시 while문으로 가서 초기화됩니다

temps = reads;

fd0

fd1

fd2

fd3

fd4

......

0

0

0

0

1

......

 

 


void error_handling(char *message)
는 생략합니다~.... 


 
참고>>

select()함수가 실행시 5초간의 유지시간 중에 값의 변화가 생기면 즉 client의 접속이 발생할 경우 for문에 있던 accept도 같이 실행되게 됩니다 client접속이 들어오게 되면 바로 접속 성공메시지 발생하기 때문인 것 같습니다

 


=[JAVA의 배열]=


예제를 통하여 java배열의 형태를 살펴 봅시다

예제만 보시면 아주쉽게 배열을 이해 할 수 있습니다!!
 

예제1) 수형 배열10 개를 선언하시오

int [] a = new int[10];

=int a[] = new int[10]; 허용합니다

 

예제2) 케릭터형 배열을 선언과 동시에 초기화를 하시오

char [] b = {a,b,c}

 

예제3)초기화를 하지 않았다면 선언후에 초기화는 어떻게 하는가?

a[0] = 1;

a[1] = 2;

 

예제4) 정수형 배열 odd[4]만들고 아래와 같이 입력한후 출력하시오

1

3

5

7

 

출력

1 3 5 7


       
public static void main(String[] args) {

               // TODO Auto-generated method stub

               int[] odd = new int[4];

               int cnt = 1;          

       

               for(int i=0;i<odd.length;i++)

               {

                       odd[i] = cnt;

                       cnt += 2;

                       System.out.print(odd[i]+ " ");              

               }

}

참고

odd.length = 배열의 길이만큼을 뜻합니다

 

예제5)char alpha[26]만들고

A B C D ... Z까지 출력하시오~~


       
public static void main(String[] args) {

               // TODO Auto-generated method stub

               char[] alpha = new char[26];

               char cnt = 0;         

       

               for(char i='A';i<='Z';i++)

               {

                       alpha[cnt] = i;

                      

                       System.out.print(alpha[cnt++]+ " ");                

               }

        }

보너스 문제 소문자 z y x....a순으로 넣고 z y x....a순으로 출력하시오


       
public static void main(String[] args) {

               // TODO Auto-generated method stub

               char[] alpha = new char[26];

               char cnt = 0;         

       

               for(char i='z';i>='a';i--)

               {

                       alpha[cnt] = i;

                       System.out.print(alpha[cnt++]+ " ");                     
    
        }

 
      
}


예제를 통하여 1차원 배열에 대하여 살펴보았습니다

=[2
차원배열]=

 

(2차원 배열의 선언)

int [][] array = new int [5] [5];

                                    êê


그럼 역시 2차원 배열도 예제를 통하여 살펴 보도록 하겠습니다
(C와는 참 비슷하게 생겼습니다!!)

예제1)다음과 같이 만들어 보시오

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25


public static void main(String[] args) {

               // TODO Auto-generated method stub

               int [][] array = new int[5][5];

               int cnt = 1;

               for(int i=0;i<5;i++)

               {

                       for(int j=0;j<5;j++,cnt++)

                       {

                              array[i][j] = cnt;

                              System.out.print(array[i][j] + "\t");

                       }

                       System.out.print("\n");

               }

        }

예제2)다음과 같이 만들어 보시오

A

F

K

P

U

B

G

L

Q

V

C

H

M

R

W

D

I

N

S

X

E

J

O

T

Y

 

       public static void main(String[] args) {

               // TODO Auto-generated method stub

               char [][] array = new char[5][5];

               char cnt = 'A';

       

               for(int i=0;i<5;i++)

               {

                       for(int j=0;j<5;j++,cnt++)

                       {

                              array[j][i] = cnt;                                                  }

               }

               for(int i=0;i<5;i++)

               {

              

                       for(int j=0;j<5;j++,cnt++)

                       {

                              System.out.print(array[i][j] + "\t");

                       }

                       System.out.print("\n");

               }

        }

 

 교제ppt 그림참고

 
java 의 배열 역시 객체입니다 그래서 위 그림과 같이 C와는 다르게 heap영역에 생성이 되고 초기화 됩니다.!!
 

728x90