------

[ AD ] Port Monitor ( Try to use a Best WebSite Monitoring Tool )

------
Class Diagram 클래스 다이어그램

네트웍 / 쓰레드 / 서버 프로그램

설계

cMonitor
cVBuffer
cRingBuffer
cQueue
cIocpServer
cConnection
cLog
cSingleton
cThread

'0.일반개발 > UML' 카테고리의 다른 글

안드로이드 sequence diagram  (0) 2010.09.14
UML : 시퀀스 다이어 그램  (0) 2010.09.03
UML의 기초 : 클래스 다이어그램 (한글)  (0) 2010.09.03
Open Source Project Tigris.org  (0) 2010.09.03

ADT Plugin for Eclipse , 이글립스를 위한 ADT 플러그인

http://developer.android.com/sdk/eclipse-adt.html

Eclipse 3.4 (Ganymede) Eclipse 3.5 (Galileo)
  1. Start Eclipse, then select Help > Software Updates.... In the dialog that appears, click the Available Software tab.
    도움메뉴에서 Software Updates의 

  2. Click Add Site...(사이트 추가를 클릭)
  3. In the Add Site dialog that appears, enter this URL in the "Location" field:
    https://dl-ssl.google.com/android/eclipse/

    Note: If you have trouble acquiring the plugin, try using "http" in the Location URL, instead of "https" (https is preferred for security reasons).

    Click OK.

  4. Back in the Available Software view, you should see the plugin listed by the URL, with "Developer Tools" nested within it. Select the checkbox next to Developer Tools and click Install...
  5. On the subsequent Install window, "Android DDMS" and "Android Development Tools" should both be checked. Click Next.
  6. Read and accept the license agreement, then click Finish.
  7. Restart Eclipse.
  1. Start Eclipse, then select Help > Install New Software.
    도움메뉴 에서 Install New Software를 선택

  2. In the Available Software dialog, click Add....
  3. In the Add Site dialog that appears, enter a name for the remote site (for example, "Android Plugin") in the "Name" field.

    In the "Location" field, enter this URL:

    https://dl-ssl.google.com/android/eclipse/

    Note: If you have trouble acquiring the plugin, you can try using "http" in the URL, instead of "https" (https is preferred for security reasons).

    Click OK.

  4. Back in the Available Software view, you should now see "Developer Tools" added to the list. Select the checkbox next to Developer Tools, which will automatically select the nested tools Android DDMS and Android Development Tools. Click Next.
  5. In the resulting Install Details dialog, the Android DDMS and Android Development Tools features are listed. Click Next to read and accept the license agreement and install any dependencies, then click Finish.
  6. Restart Eclipse.
재설치 / 삭제



'0.일반개발' 카테고리의 다른 글

Samsung Galaxy 안드로이드 커널 빌드  (0) 2010.10.08
안드로이드 커널 소스  (0) 2010.10.08
Template 만들기  (0) 2010.10.07
대체 편집기 /  (0) 2010.10.07
단축키  (0) 2010.10.07





Button ${button} = (Button) findViewById(R.id.${BUTTON_ID});
${button}.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent(${class}.this, ${target}.class);
        intent.setAction(Intent.ACTION_VIEW);
        startActivity(intent);
    }
});
${imp:import(android.widget.Button,android.view.View,android.view.View.OnClickListener,android.content.Intent)}${cursor}


'0.일반개발' 카테고리의 다른 글

안드로이드 커널 소스  (0) 2010.10.08
안드로이드 ADT 설치 / 삭제  (0) 2010.10.07
대체 편집기 /  (0) 2010.10.07
단축키  (0) 2010.10.07
자동완성 기능 - 이클립스 eclipse - Java-Editor-Content Assist  (0) 2010.10.07

2개의 이클립스를 띄우기 힘들때... 메소드 자동완성 기능 있고 가벼운 Ruby 에디터
http://www.jedit.org 여기 가시면 다운 받을수 있습니다.

여러가지 플러그인과 멀티 플랫폼 에디터더군요.
무료로 다운 받을수 있는 에디터,
기능 좋다는 평

jEdit is a mature programmer's text editor with hundreds (counting the time developing plugins)
of person-years of development behind it.

Some of jEdit's features include:

  • Written in Java, so it runs on Mac OS X, OS/2, Unix, VMS and Windows.
  • Built-in macro language; extensible plugin architecture. Dozens of macros and plugins available.
  • Plugins can be downloaded and installed from within jEdit using the "plugin manager" feature.
  • Auto indent, and syntax highlighting for more than 130 languages.
  • Supports a large number of character encodings including UTF8 and Unicode.
  • Folding for selectively hiding regions of text.
  • Word wrap.
  • Highly configurable and customizable.
  • Every other feature, both basic and advanced, you would expect to find in a text editor.

See the Features page for a full list.

'0.일반개발' 카테고리의 다른 글

안드로이드 ADT 설치 / 삭제  (0) 2010.10.07
Template 만들기  (0) 2010.10.07
단축키  (0) 2010.10.07
자동완성 기능 - 이클립스 eclipse - Java-Editor-Content Assist  (0) 2010.10.07
AsyncTask 왜 사용해야 하나? 흠...  (0) 2010.10.06

자동 완성 기능 - 안나올때

Window - Preferences - Java - Editor - Content Asist
- (Auto-activation) - Enable (auto-activation)

위와 같이 해주면 된다.




자동완성 기능 - 목록이 나오지 않을때..

'0.일반개발' 카테고리의 다른 글

대체 편집기 /  (0) 2010.10.07
단축키  (0) 2010.10.07
AsyncTask 왜 사용해야 하나? 흠...  (0) 2010.10.06
안드로이드 user permission 전부 전체 리스트  (0) 2010.10.05
Eclipse 사용법들  (0) 2010.10.05
CLEAN 클린
씻어내고 새롭게 태어나는 내 몸 혁명


1. 나는 뉴욕에서 병들어가고 있었다
누구나 보물상자를 가지고 태어난다
- 무한한 에너지의 보고로 통하는 무료입장권이 있다 | 과부하에 걸린 우리 몸의 해독시스템을 구출하라
| 약과 수술은 최선의 답이 아니다

클린이란 무엇인가?
의사인 내게 이런 일이 벌어지다니
- 내 머릿속에서 대체 무슨 일이? | “세상에, 10년은 젊어 보여요!”

2. 지구 전체를 뒤덮은 독소의 충격적 실체
왜 아픈 사람들이 점점 늘어나고 있는가?
- 암세포와 인간세포는 공통점이 있다
독성에 무지한 현대의학

독소는 어디에 있는가?
- 우리 몸의 표면을 형성하는 제1피부 | 피부를 덮고 있는 위험한 독성물질들
| 항균제품과 청소용품이 생활공간을 위협한다

3. 죽음을 부르는 식탁 위의 복마전
당신의 식탁이 위험하다
- 슈퍼마켓에 홀딱 반한 도시생활자의 딜레마

‘무엇을 위해’ 먹는지 잊어버린 사람들
- 식단공식에 집착하는 사람들, 위기에 처하다 | 빨리 멋진 몸을 만들 것인가, 건강하게 오래 살 것인가
| 죽음을 무릅쓴 다이어트 열풍 | 거칠고 난폭한 방식에서 벗어난 생식과 채식주의 운동

결국 자연의 방식을 따르는 게 답이다

4. 몸속까지 침투한 독소, 은밀히 공격을 개시하다
독소의 폭풍우, 어떻게 나타날까?
- 이유 없이 붓는 증상은 왜 나타나는 걸까?
| 변비가 위험한 것은 독소의 재흡수 때문이다
| 알레르기의 원인은 환경이 아니라 음식이다
| 환자를 더 우울하게 만드는 우울증 약의 부작용
| 과민성대장증후군과 세로토닌은 어떤 관계?

몸을 망가뜨리는 정체불명의 증상들, 뿌리는 하나다
- 우리 몸에서 일어나고 있는 ‘이상기후 현상’| 무엇이 몸을 산성화시키나?
| 칼로리는 과잉이나 영양은 결핍된 상태 | 몸속에 난 산불을 진화하라
| 보이지 않는 독소의 공격, 생각이 많아도 독이 된다?

5. 클린으로 몸 속 독소를 깨끗이 씻어내라
모든 것은 대장에서 시작된다
- 장 속의 좋은 세균은 우리 몸의 국토안보부
| 아군과 적군을 헷갈린 면역계의 치명적인 공격

두 번째 두뇌의 놀라운 비밀
- 목마르기 전에 우물을 파라

타고난 유전자는 과연 ‘운명’인 걸까?
- 유전자 발현은 음식의 명령을 따른다 | 유전자가 의사에게 처방전 쓰는 법을 알려준다면?

6. Before : 클린 프로그램 준비하기
우리 몸이 가진 놀라운 자연치유력
- 자가치유능력을 되살리려면 현대의학의 맹점을 직시하라

클린은 어떤 효과가 있는가?
- 오래되고 꽉 막힌 것을 버리고 새로 시작하기 | 똑똑한 우리 몸은 스스로를 정화할 수 있다

우리 몸의 에너지 경제학
- 영양가도 없는 것을 소화시키느라 에너지가 낭비되고 있다 

해독의 시작을 알리는 몸의 신호를 켜는 법
해독과정의 기본 메커니즘
- 간 해독작업의 필수요소 | 여러 가지 해독 프로그램들

왜 클린인가?
- 클린 프로그램을 하면 안 되는 사람

몸이 전하는 메시지를 제대로 해석하라
- 처음 사흘은 힘들지만 몸은 금방 적응한다 | 대체 왜 이렇게 아픈 사람이 많은 걸까?

스케줄을 조정하고 주방을 청소하라
- 당신의 스케줄에 클린을 넣어라 | 가장 시급한 것은 주방 청소 | 생활 속 독소를 없애라

제거식이요법으로 미리 준비하기
- 방해물은 없애고 모자라는 것은 채우기 | 신중하게 접근해야 할 pH의 문제
| 고치지 못하는 병은 없다, 고치지 못하는 환자가 있을 뿐

7. Start : 클린 프로그램 따라 하기
클린 프로그램 시작하기
- 클린일지를 쓰고 사진을 찍어둔다

식사의 규칙
- 12시간 단식, 작전이 필요하다 | 클린 레시피에 소개된 음식들
| 상황에 맞게 변형시킬 때 지켜야 할 규칙 | 마실 것을 고르는 기준과 해독에 도움을 주는 음식들

몸속 해독작용을 응원하라
- 몸 밖으로 배출시키기 | 운동은 효과를 극대화시킨다 | 휴식과 수면

보이지 않는 독, 스트레스 비우기
- 생각을 멈추고 느낌에 집중하라

배고픔 다루기
클린 계획표
- 첫째 주 : 가장 힘들지만 금방 괜찮아진다
| 둘째 주 : 체내에서 가장 격렬한 적응이 일어난다
| 셋째 주 : 눈에 띄는 변화와 최고의 기분을 느낀다

8. After : 클린 유지하기
클린 마무리하기
자신에게 유독한 자극물 확인하기

깨끗한 상태 유지하기
- 클린 이후의 식습관 | 정기적인 해독 | 불필요한 스트레스와 독소에 노출되는 일 줄이기
| 혈액검사로 혈액 속의 주요 성분 수치를 체크하라 | 갑상샘 기능

에필로그 - 조금만 바꿔도 모든 것이 달라진다

부록1 클린 레시피 42
- 스무디 | 수프 | 주스 | 생선요리 | 고기요리(닭고기 또는 양고기) | 채식요리
부록2 심장병과 독소 - ‘해독’이라는 렌즈로 철저히 조사하자 | 모든 규칙에는 예외가 있다
부록3 유용한 정보들 - 생활 속의 중금속들 | 처방약과 영양결핍 | 해독작용을 하는 영양소
DLL 내에서 정의된 Function을 export하기 위해서는 “__declspec(dllexport)” 를 사용한다.

“__declspec”은 MS만의 C, C++의 확장된 syntax로서, 확장된 storage-class 정보를 정의한다.

“dllexport”는 storage-class의 한 속성으로, DLL의 Function, Data, Object를 export할 수 있도록 하여준다.

반대로 DLL내의 Function을 import하기 위해서는 “dllimport” 속성을 사용한다.

Win32 환경에서는 Function Export/Import를 위하여 이것을 이용하며,

Win32 이전의 Windows 환경에서 사용되던 module-definition file (.DEF)을 사용하지 않는다.
단, VB와 호환가능한 DLL을 제작하는 경우, module-definition file을 사용하도록 한다.


#ifdef DLLTEST_EXPORTS
#define DLLFunction __declspec(dllexport)
#elseif
#define DLLFunction __declspec(dllimport)
#endif


DLL의 Project Settings에 Preprocessor definitions에 “프로젝트명_EXPORTS”의 형식으로 정의 되어 있다

IO Completion Port 작성 하기



1. MFC 프로젝트 - 다이얼로그 방식

프로젝트명 : IOCompletionPort 

생성 : 
자동 ( IOCompletionPortDlg.h / IOCompletionPortDlg.cpp / class CIOCompletionPort() {} /
        로 생김(자동으로 C가 붙음) )


2. 다이얼로그에  ListBox Control 추가

---- 흠

3. 버튼을 옮겨서 : 서버 시작 버튼을 만들고.....클릭시 함수처리부분에서 호출 및 사용될  class 정의


4.  class 정의 :  cIOCompletionPort

5. 클래스 마법사에서 ListBox 멤버 변수 작성 - IOCompletionPortDlg.cpp
6. ListBox에 문자 출력하는 함수 작성 - IOCompletionPortDlg.cpp
IOCompletionPortDlg.h
// 흠 흠 흠
#include "afxwin.h"
#include "resource.h"

#include "cIOCompletionPort.h"

#define	LISTEN_PORT		8000

///..........

public:
	void OutputMsg(char * szOutputString,...);
	CListBox m_ctOutput;
	boolean		m_bServerStarted;
	cIOCompletionPort m_IOCompletionPort;

	afx_msg void OnBnClickedStartserver();
	afx_msg void OnBnClickedCancel();



IOCompletionPortDlg.cpp

/// 사용자 추가
void CIOCompletionPortDlg::OutputMsg(char * szOutputString,...)
{

	char szOutStr[1024];
	va_list argptr;

	va_start(argptr, szOutputString) ;
	vsprintf( szOutStr, szOutputString, argptr );
	va_end(argptr);

	
	//  CListBox에 추가

	// 속성 - > 구성속성->일반 -> 멀티 바이트 문자 조합 MBCS
	//m_ctOutput.SetCurSel( m_ctOutput.AddString( szOutStr ) );

	m_ctOutput.InsertString(0, szOutStr) ;

}



void CIOCompletionPortDlg::OnBnClickedStartserver()
{
	// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.

		if ( ! m_bServerStarted  ) {
			OutputMsg("0.----서버 ");

			m_IOCompletionPort.SetMainDlg(this);
			bool bRet = m_IOCompletionPort.InitSocket();

			OutputMsg("1.----포트:%d", LISTEN_PORT );
			m_IOCompletionPort.BindandListen(LISTEN_PORT);

			OutputMsg("2.----가동 " );
			m_IOCompletionPort.StartServer();

			m_bServerStarted=true;
		} else {
			OutputMsg("****************서버 가동중 : 누르지 마세요 ******************");
		}

}


void CIOCompletionPortDlg::OnBnClickedCancel()
{
	// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.

	m_IOCompletionPort.DestroyThread();

	CDialogEx::OnCancel();
}


cIOCompletionPort.h


// 1. 패킷 사이즈
#define MAX_SOCKBUF		1024
// 2. 클라이언트 수
#define		MAX_CLIENT	1024
// 3. 쓰레스 수
#define		MAX_WORKERTHREAD	4


enum	enumOperation {
	OP_RECV,
	OP_SEND
};

/// WSAOVERLAPPED 구조체를 확장시켜 필요한 정보 추가
struct stOverlappedEx {
	WSAOVERLAPPED		m_wsaOverlapped;	// Overlapped I/O 구조체
	SOCKET				m_socketClient;		// client socket
	WSABUF				m_wsaBuf;			// Overlapped I/O 작업 버퍼
	char				m_szBuf[MAX_SOCKBUF];	// 데이타 버퍼
	enumOperation		m_eOperation;			// 작업 동작 종류
};
/// client 정보를 담기 위한 구조체
struct	stClientInfo {
	SOCKET				m_socketClient;		// 클라이언트와 연결되는 소켓
	stOverlappedEx		m_stRecvOverlappedEx;	// Recv Overlapped I/O 작업을 위한 변수
	stOverlappedEx		m_stSendOverlappedEx;	// Send Overlapped I/O 작업을 위한 변수

	/// 생성자에서 멤버 변수들을 초기화
	stClientInfo() 
	{
		m_socketClient = INVALID_SOCKET;
		ZeroMemory( &m_stRecvOverlappedEx, sizeof(m_stRecvOverlappedEx) );
		ZeroMemory( &m_stSendOverlappedEx, sizeof(m_stSendOverlappedEx) );
	}
};


class CIOCompletionPortDlg;

class cIOCompletionPort
{
public:
	cIOCompletionPort(void);
	~cIOCompletionPort(void);
	bool InitSocket(void);

	bool BindandListen(int nPort);
	bool StartServer(void);
	bool CreateWorkerThread(void);
	bool CreateAccepterThread(void);
	stClientInfo * GetEmptyClientInfo(void);
	bool BindIOCompletionPort(stClientInfo * pClientInfo);

	bool BindRecv(stClientInfo * pClientInfo);
	bool SendMsg(stClientInfo * pClientInfo, char * pMsg, int nLen);
	void WorkerThread(void);
	void AccepterThread(void);
	void SetMainDlg(CIOCompletionPortDlg * pMainDlg);
	void DestroyThread(void);
	void CloseSocket(stClientInfo * pClientInfo, bool bIsForce=false);
private:
	// 1. 클라이언트 정보 저장 구조체
	stClientInfo *	m_pClientInfo;

	// 2. 클라이언트 접속을 받기위한 리슨 소켓
	SOCKET			m_socketListen;

	// 3. 접속 되어 있는 클라이언트 수
	int				m_nClientCnt;

	// 4. 메인 윈도우 포인터
	CIOCompletionPortDlg *		m_pMainDlg;

	// 5. 작업 스레드 핸들
	HANDLE			m_hWorkerThread[MAX_WORKERTHREAD];

	// 6. 접속 스레드 핸들
	HANDLE			m_hAccepterThread;

	// 7. CompletionPort 객체 핸들
	HANDLE			m_hIOCP;

	// 8. 작업 스레드 동작 플래그
	bool			m_bWorkerRun;

	// 9. 접속 스레드 동작 플래그
	bool			m_bAccepterRun;

	// 10. 소켓 버퍼
	char			m_szBuf[1024];

};



cIOCompletionPort.cpp
#include "StdAfx.h"

#include "cIOCompletionPort.h"

//// 흠
#include "IOCompletionPortDlg.h"

/// 쓰레드 만들기 
/// WSARecv , WSASend의 Overlapped I/O 작업을 위한 
unsigned int WINAPI	CallWorkerThread(LPVOID p)
{
	cIOCompletionPort * pOverlappedEvent = (cIOCompletionPort *)p;

	pOverlappedEvent->WorkerThread();

	return 0;
}
unsigned int WINAPI	CallAccepterThread(LPVOID p)
{
	cIOCompletionPort * pOverlappedEvent = (cIOCompletionPort *)p;

	pOverlappedEvent->AccepterThread();

	return 0;
}
/// 
cIOCompletionPort::cIOCompletionPort(void)
{
	/// 모든 멤버 변수들의 초기화
	m_pMainDlg = NULL;
	m_bWorkerRun	= true;
	m_bAccepterRun	= true;
	m_nClientCnt = 0;
	m_hAccepterThread = NULL;
	m_hIOCP	= NULL;
	m_socketListen = INVALID_SOCKET;
	ZeroMemory(m_szBuf, 1024);
	for ( int i=0; i < MAX_WORKERTHREAD; i++ ) {
		m_hWorkerThread [i] = NULL;
	}
	m_pClientInfo = new stClientInfo[MAX_CLIENT];
}


cIOCompletionPort::~cIOCompletionPort(void)
{
	// 윈속 사용 해재
	WSACleanup();
	// 다 사용한 객체 삭제
	if ( m_pClientInfo ) 
	{
		delete[] m_pClientInfo;
		m_pClientInfo = NULL;
	}
}


bool cIOCompletionPort::InitSocket(void)
{
	WSADATA	wsaData;

	// 윈속 버젼 2.2
	int nRet = WSAStartup( MAKEWORD(2,2) , &wsaData);
	if ( 0 != nRet ) {

		m_pMainDlg->OutputMsg("[에러]WSAStartup() 실패:%d:",WSAGetLastError() );

		return false;
	}
	m_socketListen = WSASocket(AF_INET, SOCK_STREAM,
					IPPROTO_TCP, NULL, NULL, WSA_FLAG_OVERLAPPED );

	if ( INVALID_SOCKET == m_socketListen ) {

		m_pMainDlg->OutputMsg("[에러]WSASocket() 실패:%d:",WSAGetLastError() );

		return false;

	}
	m_pMainDlg->OutputMsg(" InitSocket() 성공" );
	///
	return true;
}




bool cIOCompletionPort::BindandListen(int nPort)
{

	SOCKADDR_IN		stServerAddr;

	stServerAddr.sin_family = AF_INET;

	stServerAddr.sin_port = htons(nPort);

	stServerAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

	int nRet = bind( m_socketListen, (SOCKADDR *)&stServerAddr, sizeof(SOCKADDR_IN) );
	if ( 0 != nRet ) {

		m_pMainDlg->OutputMsg("[에러] bind() 실패:%d:",WSAGetLastError() );

		return false;

	}
	nRet = listen( m_socketListen, 5 ) ;
	if ( 0 != nRet ) {

		m_pMainDlg->OutputMsg("[에러] listen() 실패:%d:",WSAGetLastError() );

		return false;

	}
	m_pMainDlg->OutputMsg(" BindandListen() 성공" );
	///
	return true;
}





bool cIOCompletionPort::CreateWorkerThread(void)
{

	unsigned int uiThreadId = 0;

	/// Waiting Thread Queue에 대기 상태로 넣을 쓰레드들 생성
	/// 권장하는 개수 : cpu *2 +1

	for ( int i =0; i < MAX_WORKERTHREAD; i++ ) 
	{

		m_hWorkerThread[i] = (HANDLE)_beginthreadex(NULL, 0,
							&CallWorkerThread,
							this,
							CREATE_SUSPENDED,
							&uiThreadId);
		if ( m_hWorkerThread[i] == NULL ) 
		{
			m_pMainDlg->OutputMsg("[에러] CreateWorkerThread() 실패:%d:",GetLastError() );

			return false;
		}
		ResumeThread( m_hWorkerThread[i] );
	}


	m_pMainDlg->OutputMsg(" CreateWorkerThread() 성공" );
	///
	return true;
}


bool cIOCompletionPort::CreateAccepterThread(void)
{

	unsigned int uiThreadId = 0;

	/// 클라이언트 접속 요청을 받은 쓰레드 생성
	m_hAccepterThread = (HANDLE)_beginthreadex(NULL, 0,
						&CallAccepterThread,
						this,
						CREATE_SUSPENDED,
						&uiThreadId);
	if ( m_hAccepterThread == NULL ) 
	{
		m_pMainDlg->OutputMsg("[에러] CreateAccepterThread() 실패:%d:",GetLastError() );

		return false;
	}
	ResumeThread( m_hAccepterThread );


	m_pMainDlg->OutputMsg(" CreateAccepterThread() 성공" );
	///
	return true;
}
////
bool cIOCompletionPort::BindIOCompletionPort(stClientInfo * pClientInfo)
{

	HANDLE hIOCP;

	/// socket 과 pClientInfo를  CompletionPort객체와 연결 시킨다.
	hIOCP = CreateIoCompletionPort( (HANDLE)pClientInfo->m_socketClient,
			m_hIOCP,
			reinterpret_cast( pClientInfo ),
			0);
	if ( NULL == hIOCP || m_hIOCP != hIOCP ) 
	{
		m_pMainDlg->OutputMsg("[에러] CreateIoCompletionPort() 실패:%d:",GetLastError() );

		return false;
	}


	m_pMainDlg->OutputMsg(" BindIOCompletionPort() 성공" );
	///
	return true;
}

bool cIOCompletionPort::StartServer(void)
{


	m_hIOCP = CreateIoCompletionPort( INVALID_HANDLE_VALUE,
								NULL,
								NULL,
								0);
	if ( NULL == m_hIOCP ) 
	{
		m_pMainDlg->OutputMsg("[에러] CreateIoCompletionPort() 실패:%d:",GetLastError() );

		return false;
	}

	
	bool bRet = CreateWorkerThread();
	if ( false == bRet ) 
	{
		m_pMainDlg->OutputMsg("[에러] CreateWorkerThread() 실패:%d:",GetLastError() );

		return false;
	}

	bRet = CreateAccepterThread();
	if ( false == bRet ) 
	{
		m_pMainDlg->OutputMsg("[에러] CreateAccepterThread() 실패:%d:",GetLastError() );

		return false;
	}

	m_pMainDlg->OutputMsg(" StartServer() 성공" );
	///
	return true;
}

	
bool cIOCompletionPort::BindRecv(stClientInfo * pClientInfo)
{
	DWORD	dwFlag = 0;
	DWORD	dwRecvNumBytes = 0;


	// Overlapped I/O Setting
	pClientInfo->m_stRecvOverlappedEx.m_wsaBuf.len = MAX_SOCKBUF;
	pClientInfo->m_stRecvOverlappedEx.m_wsaBuf.buf = 
		pClientInfo->m_stRecvOverlappedEx.m_szBuf;
	pClientInfo->m_stRecvOverlappedEx.m_eOperation = OP_RECV;

	
	//// 입력 버퍼 클리어 ???????????????
	//ZeroMemory(pClientInfo->m_stRecvOverlappedEx.m_szBuf, 1024);

	int nRet = WSARecv( pClientInfo->m_socketClient,
						&(pClientInfo->m_stRecvOverlappedEx.m_wsaBuf),
						1,
						&dwRecvNumBytes,
						&dwFlag,
						(LPWSAOVERLAPPED)&(pClientInfo->m_stRecvOverlappedEx),
						NULL);
	/// socket_error 이면 client socket이 끊어 진걸로 처리한다.
	if ( nRet ==  SOCKET_ERROR && ( ERROR_IO_PENDING != WSAGetLastError()  )  ) 
	{
		m_pMainDlg->OutputMsg("[에러] BindRecv WSARecv() 실패 WSAGetLastError:%d:",WSAGetLastError() );

		return false;
	}
	m_pMainDlg->OutputMsg("[알림] BindRecv WSARecv() 성공");
	return true;
}


bool cIOCompletionPort::SendMsg(stClientInfo * pClientInfo, char * pMsg, int nLen)
{
	DWORD	dwRecvNumBytes = 0;

	//전송될 메시지를 복사
	CopyMemory( pClientInfo->m_stSendOverlappedEx.m_szBuf, pMsg, nLen );


	// Overlapped I/O Setting 정보
	pClientInfo->m_stSendOverlappedEx.m_wsaBuf.len = nLen;

	pClientInfo->m_stSendOverlappedEx.m_wsaBuf.buf =
							pClientInfo->m_stSendOverlappedEx.m_szBuf;

	pClientInfo->m_stSendOverlappedEx.m_eOperation = OP_SEND;

	int nRet = WSASend( pClientInfo->m_socketClient, 
						&(pClientInfo->m_stSendOverlappedEx.m_wsaBuf),
						1,
						&dwRecvNumBytes,
						0,
						(LPWSAOVERLAPPED)&(pClientInfo->m_stSendOverlappedEx),
						NULL);
	if ( nRet == SOCKET_ERROR ) {
		m_pMainDlg->OutputMsg("[에러] SendMsg WSASend() nRet:%s:","SOCKET_ERROR" );
	}
	/// socket_error 이면 client socket이 끊어 진걸로 처리한다.
	if ( nRet ==  SOCKET_ERROR && ( WSAGetLastError() != ERROR_IO_PENDING )  ) 
	{
		m_pMainDlg->OutputMsg("[에러] SendMsg WSASend() 실패 WSAGetLastError:%d:",WSAGetLastError() );

		return false;
	}
			
	m_pMainDlg->OutputMsg("[알림] SendMsg WSASend() 성공");

	return true;
}
// 할당
stClientInfo * cIOCompletionPort::GetEmptyClientInfo(void)
{
	for(int i = 0; i < MAX_CLIENT; i++ ) 
	{
		if(INVALID_SOCKET == m_pClientInfo[i].m_socketClient) 
		{
			return &m_pClientInfo[i];
		}
	}
	return NULL;
}



// 사용자 접속 받는 쓰레드
void cIOCompletionPort::AccepterThread(void)
{
	SOCKADDR_IN		stClientAddr;

	int nAddrLen = sizeof(SOCKADDR_IN);
	while ( m_bAccepterRun)
	{
		// 접속 받을 구조체 인덱스 얻기
		stClientInfo * pClientInfo = GetEmptyClientInfo();
		if ( NULL == pClientInfo )
		{
			m_pMainDlg->OutputMsg("[에러] NULL == pClientInfo :%s:","Client FULL");

			return ;
		}
		// 클라이언트 접속 요청까지 대기
		pClientInfo->m_socketClient = accept ( m_socketListen,
							(SOCKADDR *)&stClientAddr, &nAddrLen );
		if ( INVALID_SOCKET == pClientInfo->m_socketClient ) {
			continue;
		}
		// I/O Completion Port객체와 소켓을 연결 시킨다.
		bool bRet = BindIOCompletionPort( pClientInfo );
		if ( false == bRet ) {
			return;
		}
		// Recv Overlapped I/O 작업을 요청한다
		bRet = BindRecv(pClientInfo);
		if ( false == bRet ) {
			return;
		}

		m_pMainDlg->OutputMsg("[클라이언트 접속] ip(%s) SOCKET(%d)",
			inet_ntoa( stClientAddr.sin_addr) ,
			pClientInfo->m_socketClient);

		m_nClientCnt ++;

	}
}


void cIOCompletionPort::WorkerThread(void)
{
	// CompletionKey를 받을 포인터 변수
	stClientInfo * pClientInfo = NULL;

	// 함수 호출 성공여부
	BOOL bSuccess = TRUE;

	// Overlapped I/O작업에서 전송된 데이타 크기
	DWORD dwIoSize = 0;

	// I/O 작업을 위해 요청한 Overlapped 구조체를 받을 포인터
	LPOVERLAPPED lpOverlapped = NULL;

	while ( m_bWorkerRun ) 
	{
		/**
		이 함수로 인해 쓰래들들은 WaitingThread Queue에 대기상태로 들어간다
		완료된 Overlapped I/O 작업이 발생하면 IOCP Queue에서 완료된 작업을 가져와 뒤처리
		그리고 PostQueuedCompletionStatus()함수에 의해 사용자 메시지가 도착되면 쓰레드 종료
		**/
		bSuccess = GetQueuedCompletionStatus( m_hIOCP,
				&dwIoSize,							// 실제 전송된 바이트
				(LPDWORD)&pClientInfo,				// Completionkey
				&lpOverlapped,						// Overlappped I/O 객체
				INFINITE);							// 대기할 시간(무한대기)
		
		// 클라이언트가 접속 끊었을 때
		//
		//  FALSE == bSuccess
		//
		if ( FALSE == bSuccess && 0 == dwIoSize ) 
		{
			m_pMainDlg->OutputMsg("[클라이언트] SOCKET(%d) 접속 끊김",	pClientInfo->m_socketClient);
			CloseSocket(pClientInfo);
			continue;
		}

		// 사용자 스레드 종료 메시지 처리
		//
		//  TRUE == bSuccess
		//

		if ( TRUE == bSuccess && 0 == dwIoSize && NULL == lpOverlapped )
		{
			//
			// WorkerThread 종료
			//
			m_bWorkerRun = false ;
			continue;
		}

		if ( NULL == lpOverlapped ) {
			continue;
		}
		stOverlappedEx * pOverlappedEx =(stOverlappedEx *)lpOverlapped;

		// Overlapped I/O Recv 작업 결과 뒤 처리
		// 
		//	OP_RECV
		//
		if ( OP_RECV == pOverlappedEx->m_eOperation ) 
		{
			pOverlappedEx->m_szBuf[dwIoSize] = NULL;
			m_pMainDlg->OutputMsg("[수신] ( %d ) bytes , msg : %s ",dwIoSize,pOverlappedEx->m_szBuf);

			// 클라이언트에 메시지를 에코한다.
			//BindRecv( pClientInfo );

			//SendMsg(pClientInfo, pOverlappedEx->m_szBuf, dwIoSize );

			//pOverlappedEx->m_eOperation = OP_SEND;
			//BindRecv( pClientInfo );

			SendMsg( pClientInfo, pOverlappedEx->m_szBuf, dwIoSize);

		}
		// Overlapped I/O Send 작업 결과 뒤 처리
		// 
		//	OP_SEND
		//
		else if ( OP_SEND == pOverlappedEx->m_eOperation ) 
		{
			m_pMainDlg->OutputMsg("[송신] ( %d ) bytes , msg : %s ",dwIoSize,pOverlappedEx->m_szBuf);
			
			//// 입력 버퍼 클리어 ???????????????
			ZeroMemory(pOverlappedEx->m_szBuf, 1024);

			BindRecv( pClientInfo );

		}
		else 
		{
			m_pMainDlg->OutputMsg("[클라이언트] SOCKET(%d) 예외 상황 ",pClientInfo->m_socketClient);
		}
		lpOverlapped = NULL;
	}
}

void cIOCompletionPort::SetMainDlg(CIOCompletionPortDlg * pMainDlg)
{
	/// .h에서 .cpp로 옮겨 놓았는데? 문제 없나?
	m_pMainDlg = pMainDlg;
}


void cIOCompletionPort::DestroyThread(void)
{
	for(int i=0; i< MAX_WORKERTHREAD; i++)
	{
		// WaitingThreadQueue에서 대기중인 쓰레드에 사용자 종료 메시지 보내기
		PostQueuedCompletionStatus( m_hIOCP,0,0,NULL);
	}
	for(int i=0; i< MAX_WORKERTHREAD; i++)
	{
		CloseHandle( m_hWorkerThread[i] );
		WaitForSingleObject ( m_hWorkerThread[i], INFINITE );
	}

	m_bAccepterRun = false;
	// Accepter Thread 종료
	closesocket( m_socketListen );
	// Thread 종료
	WaitForSingleObject( m_hAccepterThread, INFINITE );


}


void cIOCompletionPort::CloseSocket(stClientInfo * pClientInfo, bool bIsForce)
{
	struct linger stLinger = {0,0};

	if ( true ) {
		// timeout=0으로 설정되어 강제 종료. 주의 : 데이타 손실 가능성
		// right now !!!
		stLinger.l_onoff = 1;
	}
	// 데이타 송수신 모두 중단
	shutdown( pClientInfo->m_socketClient, SD_BOTH );

	// 소켓 옵션
	setsockopt( pClientInfo->m_socketClient, SOL_SOCKET, SO_LINGER,
			(char *)&stLinger, sizeof(stLinger) );
	// 소켓 연결 종료
	closesocket(pClientInfo->m_socketClient);
	pClientInfo->m_socketClient = INVALID_SOCKET;
}


http://goo.gl/70pR 

Painless Threading
고통 없는 쓰레드

AsyncTask를 사용하거나  사용하지 않더라도, 항상 기억하라 두가지 법칙 싱글 쓰레드 모델에서

Regardless of whether or not you use AsyncTask, always remember these two rules about the single thread model:

  1. Do not block the UI thread, and 

UI 쓰레드를 묶어 두지 말라

 

  1. Make sure that you access the Android UI toolkit only on the UI thread.

오직 UI 쓰레드 위에서만 안드로이드 UI 툴킷을 접근한다는 것을 명심하라

AsyncTask just makes it easier to do both of these things.

AsyncTask는 단지 이런 것의 모두를 쉽게 만들어 준다.



  • You can specify the type, using generics, of the parameters, the progress values and the final value of the task
  • The method doInBackground() executes automatically on a worker thread
  • onPreExecute(), onPostExecute() and onProgressUpdate() are all invoked on the UI thread
  • The value returned by doInBackground() is sent to onPostExecute()
  • You can call publishProgress() at anytime in doInBackground() to execute onProgressUpdate() on the UI thread
  • You can cancel the task at any time, from any thread

  • source code of Shelves (ShelvesActivity.java and AddBookActivity.java)

     Photostream (LoginActivity.java, PhotostreamActivity.java and ViewPhotoActivity.java)


    We highly recommend reading the source code of Shelves to see
    how to persist tasks across configuration changes and
    how to cancel them properly when the activity is destroyed.
    어떻게 액티비티가 파괴될때 그것들을 적절하게 취소하는가


    사용법
    클래스화
     private class DownloadFilesTask extends AsyncTask {     protected Long doInBackground(URL... urls) {         int count = urls.length;         long totalSize = 0;         for (int i = 0; i < count; i++) {             totalSize += Downloader.downloadFile(urls[i]);             publishProgress((int) ((i / (float) count) * 100));         }         return totalSize;     }     protected void onProgressUpdate(Integer... progress) {         setProgressPercent(progress[0]);     }     protected void onPostExecute(Long result) {         showDialog("Downloaded " + result + " bytes");     } }
    

    생성,행
    new DownloadFilesTask().execute(url1, url2, url3);
    

    + Recent posts