2013.07.05 06:58


제목/목차

1. 소개
2. 클라이언트와 서버간 통신 개요
3. 간단한 서버와 클라이언트 구현
3.1 서버 - 기다리는 소켓 만들기
3.2 클라이언트 - 서버로 연결
3.3 서버 - 클라이언트의 연결 시도 받아들이기
3.4 클라이언트와 서버 - 자료 주고받기
4 만든 클라이언트와 서버를 컴파일하고 테스트
4.1 파일 목록
4.2 컴파일과 테스트
5. 결론

1. 소개

소켓은 프로세스간에 자료를 교환하는 수단이다. 프로세스는 같은 컴퓨터에 있거나 네트웍으로 연결된 서로 다른 컴퓨터에 있을 수 있다. 소켓이 연결되면 한쪽이 연결을 닫을 때까지 양편 모두 자료를 보낼 수 있다.

나는 작업중인 프로젝트에 소켓이 필요해서 소켓 API 함수를 감싸는 C++ 클래스를 개발하고 다듬었다. 일반적으로 자료를 요청하는 프로그램을 클라이언트, 요청에 응답하는 프로그램을 서버라고 한다. 내가 만든 ClientSocket과 ServerSocket, 주된 두 클래스를 사용하여 클라이언트와 서버가 서로 자료를 교환할 수 있다.

이 글의 목표는 프로그램에서 ClientSocket과 ServerSocket 클래스를 사용하는 방법을 알리는 것이다. 먼저 클라이언트와 서버간 통신에대해 간단히 다룬 다음, 이 두 클래스를 사용하여 간단한 서버와 클라이언트 예제를 만들 것이다.

2. 클라이언트와 서버간 통신 개요

코드로 들어가기전에 전형적인 클라이언트와 서버간 연결 단계를 간단히 살펴보자. 다음 표는 단계들을 보여준다.

서버클라이언트
1. 기다리는 소켓(listening socket)을 만들고 클라이언트에서 연결을 기다린다.
2. 클라이언트 소켓을 만들고 서버로 연결을 시도한다.
3. 클라이언트의 연결 시도를 받아들인다.
4. 자료를 주고받는다.4. 자료를 주고받는다.
5. 연결을 닫는다.5. 연결을 닫는다.

기본적으로는 이렇다. 먼저 서버가 기다리는 소켓을 만들고 클라이언트의 연결 시도를 기다린다. 클라이언트가 자체 소켓을 만들고 서버와 연결을 시도한다. 서버는 연결을 받아들이고, 자료 교환이 시작된다. 소켓 연결을 통해 모든 자료가 전달되면 양쪽 중 하나가 연결을 닫는다.

3. 간단한 서버와 클라이언트 구현

이제 코드로 들어갈 시간이다. 이제부터 개요에서 다룬 단계를 모두 수행하는 클라이언트와 서버를 만든다. 우리는 일반적으로 일어나는 순서대로 - 예를 들어 먼저 소켓을 기다리는 서버 부분을 만든 다음 서버로 연결하는 클라이언트 부분을 만드는 등 - 구현한다. 전체 코드는 simple_server_main.cppsimple_client_main.cpp에서 볼 수 있다.

미리 소스코드를 살펴보고 실행해보려면 여기를 읽어봐라. 프로젝트 파일 목록과 어떻게 컴파일하고 테스트하는지를 설명한다.

3.1 서버 - 기다리는 소켓 만들기

첫번째 할 일은 클라이언트에서 들어오는 요청을 기다리는 간단한 서버를 만드는 것이다. 다음은 서버 소켓을 만드는 코드이다.

목록 1 : 서버 소켓 만들기 ( simple_server_main.cpp의 일부 )
#include "ServerSocket.h"
#include "SocketException.h"
#include 

int main ( int argc, int argv[] )
{
  try
    {
      // Create the server socket
      ServerSocket server ( 30000 );

      // rest of code -
      // accept connection, handle request, etc...

    }
  catch ( SocketException& e )
    {
      std::cout << "Exception was caught:" << e.description() << "\nExiting.\n";
    }

  return 0;
}


이것만으로 끝났다. ServerSocket 클래스의 생성자는 기다리는 소켓을 만드는데 필요한 소켓 API를 부른다. 자세한 사항을 감추기때문에 로컬 포트에 기다리기위해 이 클래스 객체를 생성하기만 하면 된다.

try/catch 문을 주목하라. ServerSocket과 ClientSocket 클래스는 C++의 예외처리 기능을 사용한다. 클래스 함수가 어떤 이유에서건 문제가 생기면 SocketException.h에 정의된 SocketException 형의 예외를 발생한다. 이 예외를 처리하지 않으면 프로그램이 끝나기때문에 처리해주는 것이 좋다. 위에서처럼 SocketException의 description() 함수를 사용하여 오류문을 얻을 수 있다.

3.2 클라이언트 - 서버로 연결

전형적인 클라이언트와 서버간 연결의 두번째 단계는 클라이언트가 서버로 연결을 시도하는 일이다. 코드는 방금 전에 본 서버 코드와 비슷하다.

목록 2 : 클라이언트 소켓 만들기 ( simple_client_main.cpp의 일부 )
#include "ClientSocket.h"
#include "SocketException.h"
#include 
#include 

int main ( int argc, int argv[] )
{
  try
    {
      // Create the client socket
      ClientSocket client_socket ( "localhost", 30000 );

      // rest of code -
      // send request, retrieve reply, etc...

    }
  catch ( SocketException& e )
    {
      std::cout << "Exception was caught:" << e.description() << "\n";
    }

  return 0;
}


ClientSocket 클래스 객체를 만들기만하면 리눅스 소켓을 만들어서 생성자에 주어진 호스트와 포트로 연결한다. ServerSocket 클래스와 같이 생성자가 어떤 이유에서건 문제가 생기면 오류가 발생한다.

3.3 서버 - 클라이언트의 연결 시도 받아들이기

클라이언트와 서버간 연결의 다음 단계는 서버에서 일어난다. 서버가 클라이언트의 연결 시도를 받아들이면, 두 소켓 양단간 통신 채널이 열린다.

우리는 간단한 서버에 이 기능을 추가해야 한다. 다음은 수정된 버전이다.

목록 3 : 클라이언트 연결 받아들이기 ( simple_server_main.cpp의 일부 )
#include "ServerSocket.h"
#include "SocketException.h"
#include 

int main ( int argc, int argv[] )
{
  try
    {
      // Create the socket
      ServerSocket server ( 30000 );

      while ( true )
	{
	  ServerSocket new_sock;
	  server.accept ( new_sock );

	  // rest of code -
	  // read request, send reply, etc...

	}
    }
  catch ( SocketException& e )
    {
      std::cout << "Exception was caught:" << e.description() << "\nExiting.\n";
    }

  return 0;
}

연결을 받아들이기위해 accept 함수를 호출하면 된다. 이 함수는 연결 시도를 받아들이고, 연결에 대한 소켓 정보를 new_sock에 채운다. 우리는 다음 절에서 어떻게 new_sock을 사용하는지 볼 것이다.

3.4 클라이언트와 서버 - 자료 주고받기

이제 서버는 클라이언트의 연결 요청을 받아들였고, 소켓 연결을 통해 자료를 주고받을 시간이다.

C++의 고급 기능중 하나가 연산자를 오버로딩하는 - 간단히 말해서, 연산자가 특정 작업을 하도록 만드는 - 능력이다. 나는 ClientSocket과 ServerSocket 클래스의 <<와 >> 연산자를 오버로딩하여, 연산자를 사용하여 소켓에서 자료를 읽고쓸 수 있게 만들었다. 다음은 간단한 서버의 수정된 버전이다.

목록 4 : 간단한 서버 구현 ( simple_server_main.cpp의 일부 )
#include "ServerSocket.h"
#include "SocketException.h"
#include 

int main ( int argc, int argv[] )
{
  try
    {
      // Create the socket
      ServerSocket server ( 30000 );

      while ( true )
	{

	  ServerSocket new_sock;
	  server.accept ( new_sock );

	  try
	    {
	      while ( true )
		{
		  std::string data;
		  new_sock >> data;
		  new_sock << data;
		}
	    }
	  catch ( SocketException& ) {}

	}
    }
  catch ( SocketException& e )
    {
      std::cout << "Exception was caught:" << e.description() << "\nExiting.\n";
    }

  return 0;
}

new_sock 변수는 모든 소켓 정보를 저장하고 있어서, 클라이언트와 자료를 교환하는데 사용한다. "new_sock >> data;" 줄은 "new_sock에서 자료를 읽어서 'data'라는 문자열 변수에 저장한다"는 뜻이다. 비슷하게 다음 줄은 'data'에 있는 자료를 소켓을 통해 클라이언트로 보낸다.

주의를 기울였다면 여기서 만든 것이 echo 서버임을 알 수 있을 것이다. 클라이언트가 보낸 자료는 모두 다시 클라이언트에게 그대로 되돌려진다. 우리는 자료를 보내고 서버의 응답을 출력하는 클라이언트를 작성할 수 있다.

목록 5 : 간단한 클라이언트 구현 ( simple_client_main.cpp의 일부 )
#include "ClientSocket.h"
#include "SocketException.h"
#include 
#include 

int main ( int argc, int argv[] )
{
  try
    {

      ClientSocket client_socket ( "localhost", 30000 );

      std::string reply;
      try
	{
	  client_socket << "Test message.";
	  client_socket >> reply;
	}
      catch ( SocketException& ) {}

      std::cout << "We received this response from the server:\n\"" << reply << "\"\n";;

    }
  catch ( SocketException& e )
    {
      std::cout << "Exception was caught:" << e.description() << "\n";
    }

  return 0;
}

우리는 문자열 "Test Message."를 서버로 보내고, 서버의 응답을 표준출력으로 출력한다.

4. 만든 클라이언트와 서버를 컴파일하고 테스트

우리는 ClientSocket과 ServerSocket 클래스의 기본적인 사용법을 살펴봤다. 이제 프로젝트 전체를 컴파일하여 테스트해보자.

4.1 파일 목록

예제는 아래 파일들로 구성된다.

기타:
Makefile - 이 프로젝트의 Makefile
Socket.h, Socket.cpp - 소켓 API 함수를 구현한 Socket 클래스
SocketException.h - SocketException 클래스
서버:
simple_server_main.cpp - 주파일
ServerSocket.h, ServerSocket.cpp - ServerSocket 클래스
클라이언트:
simple_client_main.cpp - 주파일
ClientSocket.h, ClientSocket.cpp - ClientSocket 클래스

4.2 컴파일과 테스트

컴파일은 간단하다. 먼저 모든 프로젝트 파일을 하위디텍로리에 저장하고, 명령행 프롬프트에 다음과 같이 입력한다.

prompt$ cd directory_you_just_created
prompt$ make

그러면 프로젝트의 모든 파일을 컴파일하여 simple_server와 simple_client 출력 파일을 만든다. 두 출력 파일을 테스트하기위해 한 명령행 프롬프트에서 서버를 실행하고, 다른 명령행 프롬프트에서 클라이언트를 실행한다.

첫번째 프롬프트:
prompt$ ./simple_server
running....



두번째 프롬프트:
prompt$ ./simple_client
We received this response from the server:
"Test message."
prompt$

클라이언트는 서버로 자료를 보내고, 응답을 읽어서 위에서처럼 표준출력으로 출력한다. 클라이언트를 원하는만큼 실행할 수 있다. 서버는 매 요청에 응답한다.

5. 결론

소켓은 프로세스간에 자료를 보내는 간단하고 효율적인 방법이다. 이 글에서 우리는 소켓 통신을 살펴보고 서버와 클라이언트 예제를 만들어봤다. 이제 당신의 프로그램에 소켓 통신을 추가할 수 있다!

신고

'Computer > CPP' 카테고리의 다른 글

멀티바이트와 유니코드  (0) 2013.07.27
BroadCasting 참고 코드  (0) 2013.07.09
Virtual Key Code  (0) 2013.07.06
키보드 이벤트 처리하기  (0) 2013.07.05
Visual Studio 2012 단축키  (0) 2013.07.05
소켓통신  (0) 2013.07.05


Posted by injunech
2013.06.07 17:09


안드로이드 작업을 하다보면 메니페스트 파일에 넣어야하는 User-permission 을 잊거나 생각이

안날경우가 있따. 그래서 일단 적어 놓는다.

</application> 밑에 추가할것 ㅋ

 

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

//위치정보 확인함
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>

//위치정보 확인함

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

//wifi 연결을 확인함
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>

//wifi 체인지를 확인함

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

//네트웍이 연결된것을 확인할수 있게함

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

//부팅완료를 확인할수있게함

<uses-permission android:name="android.permission.INTERNET"/>

// 인터넷을 사용함

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 

// 외장메모리 사용

<uses-permission android:name="android.permission.RECODER_AUDIO"/>

//녹음이 가능하게 함

 

ACCESS_CHECKIN_PROPERTIES      체크인데이터베이스의_속성테이블로_액세스
ACCESS_COARSE_LOCATION         코스_로케이션_액세스_(Cell-ID/WiFi)
ACCESS_FINE_LOCATION           파인로케이션_액세스(GPS)          
ACCESS_LOCATION_EXTRA_COMMANDS 로케이션_옵션_커맨드_액세스       
ACCESS_MOCK_LOCATION           목_로케이션_프로바이더_생성_(테스트용)
ACCESS_NETWORK_STATE           네트워크_상태_접근                
ACCESS_SURFACE_FLINGER         서피스_플링거_접근                
ACCESS_WIFI_STATE              WiFi상태_접근                     
ADD_SYSTEM_SERVICE             시스템서비스_추가                 
BATTERY_STATS                  배터리_상태                       
BLUETOOTH                      블루투스                          
BLUETOOTH_ADMIN                블루투스_어드민                   
BRICK                          디바이스_실효성_지정              
BROADCAST_PACKAGE_REMOVED      제거된_패키지에_대한_notification_브로드캐스트
BROADCAST_SMS                  SMS에_대한_브로드캐스트           
BROADCAST_STICKY               인텐트_브로드캐스트               
CALL_PHONE                     통화                              
CALL_PRIVILEGED                통화(긴급전화_포함)               
CAMERA                         카메라                            
CHANGE_COMPONENT_ENABLED_STATE 컴포넌트의_실효성_변경            
CHANGE_CONFIGURATION           컨피그_변경                       
CHANGE_NETWORK_STATE           통신상태_변경                     
CHANGE_WIFI_STATE              WiFi상태_변경                     
CLEAR_APP_CACHE                어플리케이션_캐시_클리어          
CLEAR_APP_USER_DATA            어플리케이션의_유저데이터_클리어  
CONTROL_LOCATION_UPDATES       위치정보_갱신                     
DELETE_CACHE_FILES             캐시파일_제거                     
DELETE_PACKAGES                패키지_제거                       
DEVICE_POWER                   전원상태에_대한_로우레벨_접근     
DIAGNOSTIC                     진단리소스_읽고쓰기               
DISABLE_KEYGUARD               키_가드_끄기_DUMP_덤?            
EXPAND_STATUS_BAR              상태표시줄_확장                   
FACTORY_TEST                   팩토리_테스트                     
FLASHLIGHT                     플래시라이트                      
FORCE_BACK                     포스백                            
GET_ACCOUNTS                   어카운트_획득                     
GET_PACKAGE_SIZE               패키지_획득                       
GET_TASKS                      태스크_획득                       
HARDWARE_TEST                  하드웨어테스트                    
INJECT_EVENTS                  유저이벤트_키/트랙볼              
INSTALL_PACKAGES               패키지_인스톨                     
INTERNAL_SYSTEM_WINDOW         내부_시스템윈도_활용              
INTERNET                       인터넷                            
MANAGE_APP_TOKENS              어플리케이션_토큰관리             
MASTER_CLEAR                   마스터_클리어                     
MODIFY_AUDIO_SETTINGS          오디오설정_편집                   
MODIFY_PHONE_STATE             전화상태_편집                     
MOUNT_UNMOUNT_FILESYSTEMS      파일시스템_편집                   
PERSISTENT_ACTIVITY            액티비티_지속                     
PROCESS_OUTGOING_CALLS         전화_발신처리_접근                
READ_CALENDAR                  캘린더_읽어오기                   
READ_CONTACTS                  주소록_읽어오기                   
READ_FRAME_BUFFER              프레임버퍼_읽어오기               
READ_INPUT_STATE               입력상태_읽어오기                 
READ_LOGS                      로그_읽어오기                     
READ_OWNER_DATA                owner_data읽어오기                
READ_PHONE_STATE               통화상태_읽어오기_READ_SMS_SMS읽어오기
READ_SYNC_SETTINGS             동기설정_읽어오기                 
READ_SYNC_STATS                동기상태_읽어오기                 
REBOOT                         reboot                            
RECEIVE_BOOT_COMPLETED         boot완료                          
RECEIVE_MMS                    MMS수신                           
RECEIVE_SMS                    SMS수신                           
RECEIVE_WAP_PUSH               WAP수신                           
RECORD_AUDIO                   오디오_수신                       
REORDER_TASKS                  태스크_Z오더                      
RESTART_PACKAGES               패키지_리스타트                   
SEND_SMS                       SMS송신                           
SET_ACTIVITY_WATCHER           액티비티_왓쳐지정                 
SET_ALWAYS_FINISH              액티비티_전체_종료                
SET_ANIMATION_SCALE            스케일_애니메이션_지정            
SET_DEBUG_APP                  디버그어플리케이션_지정           
SET_ORIENTATION                스크린_로테이션지정               
SET_PREFERRED_APPLICATIONS     자주_사용하는_어플리케이션_지정   
SET_PROCESS_FOREGROUND         포어그라운드_처리지정             
SET_PROCESS_LIMIT              제한처리_지정                     
SET_TIME_ZONE                  타임존_지정                       
SET_WALLPAPER                  배경화면_지정                     
SET_WALLPAPER_HINTS            배경화면_힌트_지정                
SIGNAL_PERSISTENT_PROCESSES    지속처리_시그널_지정              
STATUS_BAR                     상태표시줄_지정                   
SUBSCRIBED_FEEDS_READ          서브스트립드_피즈_읽어오기        
SUBSCRIBED_FEEDS_WRITE         서브스트립드_피즈_쓰기            
SYSTEM_ALERT_WINDOW            알림_윈도우                       
VIBRATE                        진동                              
WAKE_LOCK                      알람                              
WRITE_APN_SETTINGS             APN설정_쓰기                      
WRITE_CALENDAR                 캘린더_쓰기                       
WRITE_CONTACTS                 주소록_쓰기                       
WRITE_GSERVICES                G서비스_쓰기                      
WRITE_OWNER_DATA               owner_data쓰기                    
WRITE_SETTINGS                 설정_쓰기
WRITE_SMS                      SMS쓰기 
WRITE_SYNC_SETTINGS            동기설정_쓰기

신고


Posted by injunech
2013.05.31 11:28


FROM drawable TO bitmap :

Drawable d = ImagesArrayList.get(0);  
Bitmap bitmap = ((BitmapDrawable)d).getBitmap();

 

FROM resource id of drawable TO bitmap:

Bitmap b1 = BitmapFactory.decodeResource(context.getResources(),R.drawable.icon_resource);

 

Reference:

http://stackoverflow.com/questions/3035692/how-to-convert-a-drawable-to-a-bitmap

신고

'Computer > Android' 카테고리의 다른 글

Android Bitmap Utility(resize, crop) 클래스..  (0) 2013.07.25
android uses-permission  (0) 2013.06.07
Convert drawable to bitmap  (0) 2013.05.31
안드로이드 디렉토리 생성 및 파일 I/O  (0) 2013.05.29
Android WebView 예제  (0) 2013.05.27
Bitmap Merge  (0) 2013.05.26


Posted by injunech