Q&A

  • 소켓통신에서 주고 받음을 한 프로세서로 가능한가?
안녕하세요?

제가 지금 신용카드사와의 소켓통신을 이용한 승인에 관한 프로그램을 짜고 있습니다.

그런데 모회사와 소켓통신을 하게 되었는데... 모회사는 서버쪽이고 저는 client입니다.

server가 웹 기반입니다. 저는 델파이로 ClientSocket 콤포넌트를 사용하고 있구요..

패킷전송을 합니다.

제가 알기로는 클라이언트 콤포넌트는 패킷을 보낼때는 ClientSocket1.Socket.SendBuf(보낸패킷,길이)

받을때는 클라이언트의 OnRed 이벤트에서 패킷을 받아서 처리하는 걸로 알고 있어요...(맞나?)

예를 들어...

procedure TForm1.Timer1Timer(Sender: TObject);

begin

ClientSocket1.Socket.SendBuf(보낸패킷,길이);

처리~~~

end;



procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);

begin

Socket.receivebuf(받은패킷,길이);

처리~~~

end;



위와 같이 하는 걸로 알고 있습니다.

지금 제가 할 것은 배치 작업으로 타이머로 1초~2초 마다 수백건의 데이타를 보내고 결과를 받아서 처리

해야 합니다. "for ~ loop"을 돌면서 계속 보내고 받으려고 합니다.

그런데 클라이언트 콤포넌트는 보내고 받는 프로세서가 따로 있잖아요....

(즉 보내고 받는 프로세서가 다르다는 거죠)

근데 모회사쪽이 웹 기반이므로 한건 받고 보내고 다음건 받고 보내고 이런씩이거든요...



저는 for 문은 돌면서 계속 보낼수 밖에 없잖아요....



모회사쪽 말은 클라이언트 에서 for문을 돌면서 for문 안에서 보내고 받는 즉 ...큐 개념이 아닌 단

한건마다 처리를 해야 한다고 하는군요...



지금까지 저는 개발을 for문을 돌면서 만약 1000건이 있으면 무조건 보낸다는 거였죠...그리고 오면 무조건 받는

다는 개념으로 생각했거든요...

그렇게 하면 안된다는 군요...

무조건 한건 보내고 받아야만 한다는 군요.그리고 그 다음 건 보내고....뭐 이런 식으로...



질문.1

이것이 클라이언트 소켓 콤포넌트에서 가능한가요?

제 생각에는 보내는 소스내에서 for문 안에서 받은 패킷을 처리를 해야 하나요?(할수 있나?)



질문.2

반드시 패킷을 받을때는 ClientSocket1Read에서 해야 하나요?

보낼때는 다른 이벤트에서 하는데....받을때는 꼭 ClientSocket1Read에서 하나요?





고수님들?

어떻게 생각합니까?

제가 어떻게 해야 하죠?

훌륭한 충고 부탁드립니다.



2  COMMENTS
  • Profile
    솔뫼마당 2001.03.28 00:11
    분명한 내용은 for 문으로 해결해서는 안된다는 것입니다.

    소켓 전송은 CRC-32나 기타 프로토콜처럼 동기식으로 처리하여야 한다는 것입니다.

    즉, 받을 준비가 되었다는 Ready 신호를 보내고, 보냈으면 받겠다는 신호와

    받고 나서는 잘 받았다는 신호, 계속보내겠다는 신호를 받고 또한 끝일 경우에는

    그 신호를 받고 종료신호를 보내야 한다는 것입니다.



    아래 내용은 검색엔진에 데이터 요청을 하고 그 결과를 기다리고

    반복적으로 데이터를 주고 받는 프로세스를 작성한 예입니다.

    참고하시기 바랍니다.



    참고로 전송단위를 2048바이트 단위로 처리하였습니다.



    procedure TForm1.CSocketRead(Sender: TObject;

    Socket: TCustomWinSocket);

    var

    tReceiveText, tReadMsg, tSendMsg, tGubun: String;

    i: Integer;

    QryCnt: Integer;

    begin

    if (SERVER_PORT <= 0) then Exit;



    tReceiveText := Socket.ReceiveText;

    tGubun := Copy(tReceiveText, 1, 1);

    if tGubun = '' then tGubun := #32;



    case tGubun[1] of

    '0'..'9' : begin

    tReadMsg := Copy(tReceiveText, 1, SIZE_QRYCNT);

    QryCnt := StrToIntDef(tReadMsg,0);

    Label17.Caption := Format('검색갯수: %d', [QryCnt]);



    (* 준비신호 전송 *)

    if QryCnt = 0 then

    begin

    SocketErrorCode := SOCKET_ERROR;

    ModalResult := mrOk;

    Exit;

    end;



    tSendMsg := Format('%1s%2047s', ['R', #32]);

    CSocket.Socket.SendText(tSendMsg);

    end;



    'C' : begin

    ReceiveTextSplit(tReceiveText);



    (* 계속 메시지 전송 *)

    tSendMsg := Format('%1s%2047s', ['R', #32]);

    CSocket.Socket.SendText(tSendMsg);

    end;



    'E' : begin

    ReceiveTextSplit(tReceiveText);



    (* 전송 완료 메시지 전송 *)

    tSendMsg := Format('%1s%2047s', ['Z', #32]);

    CSocket.Socket.SendText(tSendMsg);



    ModalResult := mrOk;

    Exit;

    end;

    end;

    end;



    procedure TForm1.ReceiveTextSplit(ReceiveText: String);

    var

    s, tmp: String;

    begin

    s := Trim(Copy(ReceiveText, 2, SID_SIZE * SID_CNT));



    while s <> '' do

    begin

    tmp := Trim(Copy(s, 1, SID_SIZE));

    s := Trim(Copy(s, SID_SIZE+1, Length(s)-SID_SIZE));



    if tmp <> '' then

    if ListBox1.Items.IndexOf(tmp) = -1 then

    ListBox1.Items.Add(tmp);

    end;

    end;





    초심자 wrote:

    > 안녕하세요?

    > 제가 지금 신용카드사와의 소켓통신을 이용한 승인에 관한 프로그램을 짜고 있습니다.

    > 그런데 모회사와 소켓통신을 하게 되었는데... 모회사는 서버쪽이고 저는 client입니다.

    > server가 웹 기반입니다. 저는 델파이로 ClientSocket 콤포넌트를 사용하고 있구요..

    > 패킷전송을 합니다.

    > 제가 알기로는 클라이언트 콤포넌트는 패킷을 보낼때는 ClientSocket1.Socket.SendBuf(보낸패킷,길이)

    > 받을때는 클라이언트의 OnRed 이벤트에서 패킷을 받아서 처리하는 걸로 알고 있어요...(맞나?)

    > 예를 들어...

    > procedure TForm1.Timer1Timer(Sender: TObject);

    > begin

    > ClientSocket1.Socket.SendBuf(보낸패킷,길이);

    > 처리~~~

    > end;

    >

    > procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);

    > begin

    > Socket.receivebuf(받은패킷,길이);

    > 처리~~~

    > end;

    >

    > 위와 같이 하는 걸로 알고 있습니다.

    > 지금 제가 할 것은 배치 작업으로 타이머로 1초~2초 마다 수백건의 데이타를 보내고 결과를 받아서 처리

    > 해야 합니다. "for ~ loop"을 돌면서 계속 보내고 받으려고 합니다.

    > 그런데 클라이언트 콤포넌트는 보내고 받는 프로세서가 따로 있잖아요....

    > (즉 보내고 받는 프로세서가 다르다는 거죠)

    > 근데 모회사쪽이 웹 기반이므로 한건 받고 보내고 다음건 받고 보내고 이런씩이거든요...

    >

    > 저는 for 문은 돌면서 계속 보낼수 밖에 없잖아요....

    >

    > 모회사쪽 말은 클라이언트 에서 for문을 돌면서 for문 안에서 보내고 받는 즉 ...큐 개념이 아닌 단

    > 한건마다 처리를 해야 한다고 하는군요...

    >

    > 지금까지 저는 개발을 for문을 돌면서 만약 1000건이 있으면 무조건 보낸다는 거였죠...그리고 오면 무조건 받는

    > 다는 개념으로 생각했거든요...

    > 그렇게 하면 안된다는 군요...

    > 무조건 한건 보내고 받아야만 한다는 군요.그리고 그 다음 건 보내고....뭐 이런 식으로...

    >

    > 질문.1

    > 이것이 클라이언트 소켓 콤포넌트에서 가능한가요?

    > 제 생각에는 보내는 소스내에서 for문 안에서 받은 패킷을 처리를 해야 하나요?(할수 있나?)

    >

    > 질문.2

    > 반드시 패킷을 받을때는 ClientSocket1Read에서 해야 하나요?

    > 보낼때는 다른 이벤트에서 하는데....받을때는 꼭 ClientSocket1Read에서 하나요?

    >

    >

    > 고수님들?

    > 어떻게 생각합니까?

    > 제가 어떻게 해야 하죠?

    > 훌륭한 충고 부탁드립니다.

    >

  • Profile
    초심자 2001.03.28 20:53
    답변에 감사합니다.

    미안하지만 질문 하나만 더 할게요....



    제가 지금 문제가 뭐냐면...

    패킷을 하나 보내고 받으면 소켓이 끊어 져 버린다는 겁니다.

    자동으로 ....

    왜 소켓콤포넌트가 자동으로 연결을 끓어 버리는 건지???

    다시 보내는 프로세서에서 클라이언트 소켓 콤포넌트에서 clienksocket.active가 false이면 true하려고 하는데

    이것이 먹히지가 않는군요...



    제가 테스트 하면서 안건데요?

    밑의 소스에서 설명을 드리면...



    처음에 active가 true이면 진행 순서가

    1번 -> 2번 -> 3번

    결과는 activer가 자동으로 false 된다는 거죠...



    처음에 active가 false이면

    1번 -> 4번에서 끝.

    1번에서 ClientSocket1.Active := true; 시켜도 true가 되지 않는거죠???



    정말 웃긴건 왜 순서가 이렇게 되느냐는 거죠?

    제가 disconnect도 하지 않았는데 자동으로 끊어 버린다는 것~

    원래 순서가 그렇게 되는 건지 아님 무슨 옵션이 있는건지?





    1.--- procedure TForm1.Button3Click(Sender: TObject);

    begin

    if not ClientSocket1.active then

    ClientSocket1.Active := true;



    getmem(get_buffer, 255);

    get_buffer := pchar(edit1.text);

    ClientSocket1.Socket.SendBuf(get_buffer^, 255);

    end;



    2.--- procedure TForm1.ClientSocket1Read(Sender: TObject;

    Socket: TCustomWinSocket);

    var s : string;

    begin

    s := Socket.ReceiveText;

    Memo1.Lines.add(s);

    end;



    3.--- procedure TForm1.ClientSocket1Disconnect(Sender: TObject;

    Socket: TCustomWinSocket);

    begin

    Memo1.Lines.Add('차단!');

    end;



    4.--- procedure TForm1.ClientSocket1Connect(Sender: TObject;

    Socket: TCustomWinSocket);

    begin

    Memo1.Lines.Add('연결!');

    end;





    원래 클라이언트 소켓 콤포넌트가 주고 받고 한 다음 자동으로 연결을 끊어 버리는 건가요?

    서버는 제 컴퓨터에서 서비스 데몬으로 항상 실행되고 있구요...

    이 데몬이 실직적인 서버와의 다리 역활을 하는거죠...

    서버단(비주얼 C++로 만들고 통신은 웹단에서 자바로 구현,다른 회사에 있음.)에서는 멀티 쓰레드로서

    하나의 차일드 스레드와 제가 만든 클라이언트 소켓과의 연결로 이루어 집니다.

    그래서 클라이언트 소켓이 끊어지고 다시 붙으려고 하면 임시로 자동 할당된소켓id가

    틀리다는(즉 쓰레드 번호가 다르다)이유로 다시 붙지않는것 같습니다.



    고수님들의 많은 충고 바랍니다.



    설명을 너무 못해서 미안합니다.. 하하하...



    부탁드립니다.