TCPIP

2013.06.13_TCP/IP_Socket설정하기_

성엽이 2013. 6. 13. 17:39


▶ TCP/IP_Socket설정하기_ 개념 설명.


: IP주소(4byte) + PORT(2byte) = 6byte 차지함. 

: Server 는 항상 고정적, Client 는 항상 유동적,




DNS Server 란 Domain name service Server 를 뜻함. 이름으로 검색하면 DNS Server에 접속하여 IP주소로 변환시켜서 반환하고, 주소를 보내면 이름으로 반환해줌.

심볼테이블 개념이라고 보면 되겠다. 







▶ server.c

#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define  MAXPENDING 5 // 서버에서 받을 허용 인원.

int main()
{
 int servSock; // 서버소켓 
 int clntSock; // 클라이언트소켓
 int iRet;  // 저장할 변수
 unsigned char uc_buff[500];  // 채팅시에 문자열을 받는 버퍼.
 
 struct sockaddr_in echoServAddr; // 신구조체의 서버IP를 가지는 변수.
 struct sockaddr_in echoClntAddr; // 신구조체의 클라이언트IP를 가지는 변수

 unsigned short echoServPort;  // Port 번호를 가지는 변수. 2byte 크기.
 unsigned int clntLen;    // 클라이언트
  
 echoServPort = 9999; // Port 번호 0~65535 범위를 가짐.
 
 // Socket 생성
 //프로토콜패밀리결정, 소켓의형태(데이타보내는방식,SOCK_STREAM or SOCK_DGRAM)설정,
 //STREAM인지DGRAM인지에 따라서 IPPROTO_TCP , IPPROTO_UDP 로 정해줌.
 //신뢰성 : STREAM (데이터의 송수신값을 확인하며 보냄),ex)일반파일
 //비신뢰성 : DGRAM(데이터을 확인없이 한번에 보냄),ex)MP3..
 servSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
 if( 0 > servSock ) // Error 코드
 {
  printf("socket() failed\n");
  return 0;
 }
   
 // 메모리 크기를 특정값으로 초기화 여기서는 0 으로 만들어줌.
 memset(&echoServAddr, 0, sizeof(echoServAddr));
 // #define AF_INET PF_INET 2 로 define 되어있음.  패밀리선택, 우리는 PF_INET 을 쓴다.
 echoServAddr.sin_family = AF_INET; 
 // Host to Network long 으로 host의 크기를 Long형(4byte)만큼 
 // 지정하고 little-Endian -> Big-Endian방식으로 보내줌.
 // 0 을 넣어주면 Host에서 주소를 랜덤으로 줌, 고정적으로 사용하고 싶을때는 직접 주소값을 넣어줌.
 echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY);  
 // Host to Network short 으로 host의 크기를 short형(2byte)만큼
 // 지정하고 little-Endian -> Big-Endian방식으로 보내줌.
 // 0 을 넣어주면 Host에서 주소를 랜덤으로 줌, 고정적으로 사용하고 싶을때는 직접 주소값을 넣어줌.
 echoServAddr.sin_port = htons(echoServPort); // Port는 정해져있으므로 정해줌. 

 // 구조체 안에 설정한것을  소켓에다가 넣어줌. bind()
 iRet = bind(servSock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr));

 // if조건문을 위해서 iRet 변수를 지정.
 if( 0 > iRet )
 {
  printf("bind() failed\n");
  close(servSock); // 서버소켓 닫기.
  return 0;
 }
 
 // listen(서버소켓, 받을 클라이언트 수)
 // if조건문을 위해서 iRet 변수를 지정.
 iRet = listen(servSock,MAXPENDING); // Client 연결할때마다 하나씩 새로운 소켓을 얻는데 사용.
 if( 0 > iRet)
 {
  printf("listen() failed\n");
  close(servSock);
  return 0;
 }
 
 // 서버로 들어오는 클라이언트연결에대해서 accept()를 호출하면서 소켓을 만든다.
 clntLen = sizeof(echoClntAddr); // clntLen로 Client 크기를 받고, clntLen의 주소를 인자로 넘김.
 // 대기중에 있다가 서버에 접속허용을 받으면 Client 소켓을 만듬. 강제로 대기(블로킹함수)
 clntSock = accept(servSock, (struct sockaddr *)&echoClntAddr,&clntLen);
 // 소켓은 2가지가 있는데 랑데뷰소켓, 커뮤니케이션소켓이 있다.
 // accept 함수에 의해서 랑데뷰소켓이 생성됨.(랑데뷰소켓은 Clinet 의 주소를 들고있음)
 
 if( 0 > clntSock ) // 클라이언트소켓 생성 확인 구문 
 {
  printf("accept() failed\n");
  close(servSock);
  return 0;
 }

 // Network to ASCII, 클라이언트IP를 문자열[(ex)192.211.10.20]로 바꿔서 출력해줌.
 printf("Handling client IP %s\n", inet_ntoa(echoClntAddr.sin_addr)); 
 // Port 번호를 Network to Host short형 크기로 출력해줌.
 printf("Handling client PORT  %d\n", ntohs(echoClntAddr.sin_port));
 
 while(1)
 {
  iRet = read(clntSock,uc_buff,sizeof(uc_buff)-1); // read함수로 상대방말을 읽어옴.
  uc_buff[iRet] = 0;      
  write(1,uc_buff,iRet);
  if( 'q' == uc_buff[0] )
  {
   break; // 'q' 를 눌러서 종료.
  }
 }

 close(servSock); // 서버소켓을 닫기.
 close(clntSock); // 클라이언트소켓을 닫기.

 return 0;
}

 


---server.c----

server.c

--------------