C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 Q&A
C++Builder Programming Q&A
[46848] Re:[질문]인디서버에서 클라이언트로 메시지전송...
유영인 Cuperido [cuperido] 1912 읽음    2006-10-20 18:21
안녕하세요.

아래 순서같은 작업이 필요합니다.

1. 우선, 여러 클라이언트를 담을 배열이 필요합니다.
예를 들어 structure_a Client[10] 으로 하겠습니다.
structure_a 에는 아래와 같이 지정되어 있다고 합니다.

struct structure_a {
  int         Index;
  String   Name;
  String   IP;
TIdPeerThread     *SocketHandle;           // 소켓 핸들을 담을 수 있는 장소
};

2. OnConnect 이벤트에서 접속을 받으면,
Client[10]에서 빈 공간을 찾아봅니다.
0부터 9까지 쭉 돌다가.. 만약 1번 배열이 비었으면...

Client[1].Index = 1;
Client[1].Name = "클라이언트 1";
Client[1].SocketHandle = AThread;                                                 // 해당 통신 쓰레드를 저장
Client[1].IP = AThread->Connection->Socket->Binding->PeerIP;   // 이것은 Indy 버젼에 따라서 조금씩 사용법이 다릅니다.

여기서 중요한 점은, 동시에 OnConnect 이벤트가 발생했을때,
간혹 빈 공간을 찾다가 두 쓰레드가 1이라는 곳을 동시에 받아서
변수를 쓸때 데드락 혹은 크래시 현상이 발생합니다.

그래서, 크리티컬섹션 (CriticalSection) 을 사용하는데, 이 것은
이곳에서 설명하기에는 또 글이 길어지니, 한번 다른글을 살펴 보신후
작업하시다 잘 안되시면 질문을 다시 해주시면 좋겠습니다.

3. 서버에서 메시지 전송을 할 경우,
Client[] 배열을 돌다가 원하는 배열이 나오면 아래와 같이 메시지 전송을 합니다.

Client[1].SocketHandle->Connection->WriteLn("안녕하세요");

4. 이렇게 되면, 누군가 클라이언트에서 신호를 받으면 어느 Client[] 배열에
있는 클라이언트가 신호를 보내서 OnExecute 가 발생했는지를 알아야 하는데,
넘어온 인자의 AThread 비교라든지, 고유 번호인 AThread->ThreadID 을
스트럭쳐에 저장을 한다든지의 여러 방법이 있겠지만,

AThread->Data 항목이 void 형식으로 있는데, 이 것을 이용하시는 것도
좋은 방법입니다.

// 위 2번의 OnConnect 이벤트에서 추가해 주시고
AThread->Data = (TObject *)&Client[1];

// OnExecute 이벤트에서는
structure_a      *ClientInfo;
ClientInfo = (structure_a *)AThread->Data;

이런식으로 캐스팅을 하시면, 매번 신호때마다 배열을 뒤적거리는 수고를
덜 수 있습니다.


자체적으로 Indy는 이벤트 발생이 쓰레드화 되어 있기 때문에,
Indy의 Threads->LockList();  (크리티컬섹션 개념입니다)
등의 메소드를 지원하고 있습니다.

반드시 서버 프로그래밍을 하실때는, 크리티컬섹션 개념을 이해해
주어야 합니다. 그렇지 않은 경우에는 개발 환경에서는 문제가 없겠지만
필드에 나가면 엉뚱한 곳에서 계속 픽픽 죽어버리는 문제가 발생합니다.


cuperido

하안인 님이 쓰신 글 :
: 인디서버에서 클라이언트로 메시지를 전송하려면 어떻게 해야하나요.
:
: 클라이언트에서 메시지가 전송되어 왔을경우는
:
: void __fastcall TForm1::opCommServExecute(TIdPeerThread *AThread)
: {
:   String strLine;
:   String strTemp;
:   String strCmd;
:
:   try
:   {
:     try
:     {
:       strLine = AThread->Connection->ReadLn();
:       strTemp = strLine;
:       ListBox1->Items->Add(AThread->Connection->Socket->Binding->PeerIP+String("==>")+strTemp);
:
:       AThread->Connection->WriteLn("Ok");
:
:
: 위와 같이 메시지를 보내면 될것 같은데요.
:
:
: 서버에서 10개가 의 클라이언트 중 한 아이피로 보내려고 하면 어떻게 해야 하나요.

+ -

관련 글 리스트
46831 [질문]인디서버에서 클라이언트로 메시지전송... 하안인 1095 2006/10/20
46848     Re:[질문]인디서버에서 클라이언트로 메시지전송... 유영인 Cuperido 1912 2006/10/20
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.