Q&A

  • lndy(소켓) 를 이용해서 1:1 채팅을 만드는데 도와주세요.
안녕하세요.

델파이를 사랑하시는 모든 델파이 가족 여러분.

전 델파이를 시작한지 3개월 정도된 초보입니다.

전 lndy 소켓을 이용해서 1:1 프로그램을 짜고 있습니다.

한 폼에 서버, 클라이이언트를 모두 가지고 있어야 하는데요.

이곳 자료실에 올라와 있는 소스를 가지고 그냥 채팅은 아무런 이상이 없이 작동을

하는데요.

1:1을 만들려고 하는데 계속 문제가 있습니다.

보름동안 계속 같은 문제로 프로그램을 더이상 진행 하지 못하고 있습니다.

많은 고수 열분께서 알려 주세요.



클라이언트에서 서버로 접속을 하면 접속은 성공을 하는것 같은데

서버에서 접속했을때 확인 하기 위해서 간단한 메세지 창을 띄우면

뜨지 않습니다.

그런데 이상한 것은

전 지금 델파이 5.0을 사용하고 있으면 OS 는 윈도우 2000 프로페셔널입니다.

이상한 것은 같은 윈도우 2000에서는 비정상적으로 작동이 되구요

NT에서는 작동이 됩니다.

즉 윈2000에서 NT에 깔려 있는 같은 프로그램으로 접속을 하면 화면에 메세지 창이

정상적으로 뜹니다.

그런데 NT, 혹은 같은 윈도우 2000에서 소켓을 날리면

받지를 못합니다.



하지만 서로 양쪽에서 같은 포트로 (윈도우 2000) 소로를 1:1로 연결하면

아무런 이상없이 채팅이 됩니다.

또 한가지 클라이언트에서 서버에 접속을 했을때 하나의 폼을 생성해서 띄울려고 하거든요

그런데 서버에서 접속을 확인하고 폼을 띄울려고 하면 프로그램이 다운이 되요.

이유가 뭘까요?

윈소켓 버전을 확인해 봤는데 같은 소켓버전으로 테스트를 해봤거든요.

윈소켓 3.0버전이었구요.



참고로 제가 지금 시도하는 방법은요

하나의 메인 프로그램에 서버, 클라이언트 소켓을 다 가지고 있습니다.

예로 9000번 포트를 이용하고 있는데요

다른 컴에서 같은 프로그램으로 접속을 시도하면 (물론 9000번 포트겠죠)

이쪽 컴에서 9000번 포트로 접속되서

새로운 폼을 띄워서 새로운 포트번호를 부여합니다.

그 정보를 다시 접속을 요구해온 쪽으로 알려주는것이죠

그래서 1:1 채팅을 하게 할려고 하거든요

물론 새로 띄우는 폼도 서버, 클라이언트 소켓이 다 내장 되어있습니다.



지금 제가 여기서 문제가 되고 있는 부분이

윈도우 2000에서는 클라이언트가 서버에 접속을 요구하는것을 확인 하지 못한다는것이죠

그냥 정보를 주고 받는것인 됩니다.

즉 그냥 수동으로 1:1 채팅 창을 양쪽 컴에서 띄우고

상대 IP와 같은 포트를 넣고 하면 채팅은 되거든요.

그런데 서버소켓에서 접속했을때 접속했다는 메세지를 띄우고 싶은데

그것이 않됩니다.

접속 이벤트 server.connection 에 접속이 오면

해당 IP에서 접속을 요구했다는 메세지 함수를 넣었는데...



이유가 뭘까요? 많은 델파이 고수님 도와 주세요.

그럼..

4  COMMENTS
  • Profile
    이경문 2000.12.21 09:04
    procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);

    begin

    // 새로운 창을 띄운다.

    end;



    서버에서 접속이 되었을 때 창을 띄우는 코드가 다음 부분에 있을 것 같은데요,

    Synchronize를 사용하셔야 됩니다.



    정확한 에러원인은 소스를 올리시면 검토해 보도록 하겠습니다.



    델파이 완전초보자 wrote:

    > 안녕하세요.

    > 델파이를 사랑하시는 모든 델파이 가족 여러분.

    > 전 델파이를 시작한지 3개월 정도된 초보입니다.

    > 전 lndy 소켓을 이용해서 1:1 프로그램을 짜고 있습니다.

    > 한 폼에 서버, 클라이이언트를 모두 가지고 있어야 하는데요.

    > 이곳 자료실에 올라와 있는 소스를 가지고 그냥 채팅은 아무런 이상이 없이 작동을

    > 하는데요.

    > 1:1을 만들려고 하는데 계속 문제가 있습니다.

    > 보름동안 계속 같은 문제로 프로그램을 더이상 진행 하지 못하고 있습니다.

    > 많은 고수 열분께서 알려 주세요.

    >

    > 클라이언트에서 서버로 접속을 하면 접속은 성공을 하는것 같은데

    > 서버에서 접속했을때 확인 하기 위해서 간단한 메세지 창을 띄우면

    > 뜨지 않습니다.

    > 그런데 이상한 것은

    > 전 지금 델파이 5.0을 사용하고 있으면 OS 는 윈도우 2000 프로페셔널입니다.

    > 이상한 것은 같은 윈도우 2000에서는 비정상적으로 작동이 되구요

    > NT에서는 작동이 됩니다.

    > 즉 윈2000에서 NT에 깔려 있는 같은 프로그램으로 접속을 하면 화면에 메세지 창이

    > 정상적으로 뜹니다.

    > 그런데 NT, 혹은 같은 윈도우 2000에서 소켓을 날리면

    > 받지를 못합니다.

    >

    > 하지만 서로 양쪽에서 같은 포트로 (윈도우 2000) 소로를 1:1로 연결하면

    > 아무런 이상없이 채팅이 됩니다.

    > 또 한가지 클라이언트에서 서버에 접속을 했을때 하나의 폼을 생성해서 띄울려고 하거든요

    > 그런데 서버에서 접속을 확인하고 폼을 띄울려고 하면 프로그램이 다운이 되요.

    > 이유가 뭘까요?

    > 윈소켓 버전을 확인해 봤는데 같은 소켓버전으로 테스트를 해봤거든요.

    > 윈소켓 3.0버전이었구요.

    >

    > 참고로 제가 지금 시도하는 방법은요

    > 하나의 메인 프로그램에 서버, 클라이언트 소켓을 다 가지고 있습니다.

    > 예로 9000번 포트를 이용하고 있는데요

    > 다른 컴에서 같은 프로그램으로 접속을 시도하면 (물론 9000번 포트겠죠)

    > 이쪽 컴에서 9000번 포트로 접속되서

    > 새로운 폼을 띄워서 새로운 포트번호를 부여합니다.

    > 그 정보를 다시 접속을 요구해온 쪽으로 알려주는것이죠

    > 그래서 1:1 채팅을 하게 할려고 하거든요

    > 물론 새로 띄우는 폼도 서버, 클라이언트 소켓이 다 내장 되어있습니다.

    >

    > 지금 제가 여기서 문제가 되고 있는 부분이

    > 윈도우 2000에서는 클라이언트가 서버에 접속을 요구하는것을 확인 하지 못한다는것이죠

    > 그냥 정보를 주고 받는것인 됩니다.

    > 즉 그냥 수동으로 1:1 채팅 창을 양쪽 컴에서 띄우고

    > 상대 IP와 같은 포트를 넣고 하면 채팅은 되거든요.

    > 그런데 서버소켓에서 접속했을때 접속했다는 메세지를 띄우고 싶은데

    > 그것이 않됩니다.

    > 접속 이벤트 server.connection 에 접속이 오면

    > 해당 IP에서 접속을 요구했다는 메세지 함수를 넣었는데...

    >

    > 이유가 뭘까요? 많은 델파이 고수님 도와 주세요.

    > 그럼..

  • Profile
    델파이 완전초보자 2000.12.21 20:39
    답변 감사합니다.

    제가 하고 있는 소스일부입니다. 지적해 주세요.



    참고로 윈도우 2000에서는 아무런 반응도 없습니다.

    아래 소스처럼 처음 접속이 되면 접속을 시도한 클라이언트 IP를

    출력하도록 했는데 윈도우 2000에서는 반응이 없구요

    NT 에서는 정상적으로 접속처리가 되는데 아래 과정에서 폼을 띄울때

    프로그램이 멈춰 버립니다.

    꼭 좀 알려주세요.



    procedure TMainForm.IdTCPServer1Connect(AThread: TIdPeerThread);

    begin



    // 현재 대화를 요구한 사람의 IP를 얻는다.

    ChatQueryIP := AThread.Connection.Binding.PeerIP;

    // 확인하기 위해서 Message 창을 이용했습니다.

    ShowMessage (ChatQueryIP);



    // 요구한 사람의 ID를 얻는다.

    with LoginQuery do

    begin

    SQL.Clear;

    DatabaseName :=DBName;

    SQL.Add('SELECT * FROM LoginTable ');

    SQL.Add('where IPaddress = :PARAMSTRING');

    ParamByName('PARAMSTRING').AsString := ChatQueryIP;

    Open;

    if Eof = False then

    begin

    // ChatQueryName, ChatQueryID, ChatQueryIP 는 모두 전역 변수로 선언되어있슴.

    ChatQueryName := FieldByName('UserName').AsString;

    ChatQueryID := FieldByName('ID').AsString;

    end

    else

    exit;

    Close;

    end;



    { // 처음에 이렇게 했다가 나중에 IdTCPServerExecute 함수 안에서 폼을 생성하도록 했습니다.

    모두다 창이 뜨면서 프로그램이 다운 됩니다.

    ChatForm := TChatForm.Create(Self);

    ChatForm.CaptionLabel.Caption := ' 1:1 채팅 [ ' + ChatQueryName + ':' + ChatQueryID + ' ]';

    ChatForm.Left := MainForm.Left + 136;

    ChatForm.Top := MainForm.Top + 60;

    ConnectIP := ChatQueryIP;

    ChatForm.Show;

    }

    end;



    procedure TMainForm.IdTCPServerExecute(AThread: TIdPeerThread);

    var

    ReceivePort, ReceiveName, ReceiveID: String;

    begin

    With AThread.Connection do

    begin

    // Client로 부터 사용할 포트 정보를 받는다.

    // 정보를 순서대로 사용포트, 이름, ID로 넘겨 받는다.

    ReceivePort := ReadLn;

    ReceiveName := ReadLn;

    ReceiveID := ReadLn;

    // 정상적으로 받았는지 확인하기위한 message 창

    ShowMessage(ReceiveString + #13+ #11 + ReceivePort + #13+ #11 + ReceiveName + #13+ #11 +ReceiveID);

    end;

    Disconnect;

    end;



    // 아래 부분은 IdTCPServerConnect 함수에서 하던것을 이곳에서 처리하도록 했습니다.

    // 이곳 역시 마찬가지로 폼이 생성되는 과정에서 프로그램이 다운됩니다.

    ChatForm := TChatForm.Create(Self);

    ChatForm.CaptionLabel.Caption := ' 1:1 채팅( ' + ReceiveName + ' )';

    ChatForm.Left := MainForm.Left + 136;

    ChatForm.Top := MainForm.Top + 60;



    ChatForm.ChatTCPClient.Host := ChatQueryIP;

    ChatForm.ChatTCPClient.Port := StrToInt(ReceivePort);

    ChatForm.ChatTCPServer.DefaultPort := StrToInt(ReceivePort);

    ChatForm.ChatTCPServer.Active := True;

    ChatForm.Show;



    end;





  • Profile
    이경문 2000.12.23 12:09
    일단 Connect부분만 수정해 보도록 하겠습니다.

    Connect될때 처리되어야 할 코드를 ShowChatForm이라는 멤버 프로시져를 다음과 같이 만들구요, Connect되었을 때 Synchronize(ShowChatForm)해 주면 됩니다.

    Execute에서도 마찬가지로 화면에 보여줘야 할 부분은 반드시 프로시져를 만들고 Synchronize해 주시기 바랍니다.



    procedure TMainForm.ShowChatForm;

    begin

    // 확인하기 위해서 Message 창을 이용했습니다.

    ShowMessage (ChatQueryIP);

    // 요구한 사람의 ID를 얻는다.

    with LoginQuery do

    begin

    SQL.Clear;

    DatabaseName :=DBName;

    SQL.Add('SELECT * FROM LoginTable ');

    SQL.Add('where IPaddress = :PARAMSTRING');

    ParamByName('PARAMSTRING').AsString := ChatQueryIP;

    Open;

    if Eof = False then

    begin

    // ChatQueryName, ChatQueryID, ChatQueryIP 는 모두 전역 변수로 선언되어있슴.

    ChatQueryName := FieldByName('UserName').AsString;

    ChatQueryID := FieldByName('ID').AsString;

    end

    else

    exit;

    Close;

    end;

    ChatForm := TChatForm.Create(Self);

    ChatForm.CaptionLabel.Caption := ' 1:1 채팅 [ ' + ChatQueryName + ':' + ChatQueryID + ' ]';

    ChatForm.Left := MainForm.Left + 136;

    ChatForm.Top := MainForm.Top + 60;

    ConnectIP := ChatQueryIP;

    ChatForm.Show;

    end;



    procedure TMainForm.IdTCPServer1Connect(AThread: TIdPeerThread);

    begin

    // 현재 대화를 요구한 사람의 IP를 얻는다.

    ChatQueryIP := AThread.Connection.Binding.PeerIP;

    // 확인하기 위해서 Message 창을 이용했습니다.

    Synchronize(ShowChatForm); <- ShowMessage 및 ChatForm을 띄우는 부분은 반드시 Synchronize해야 한다.



    end;







    델파이 완전초보자 wrote:

    > 답변 감사합니다.

    > 제가 하고 있는 소스일부입니다. 지적해 주세요.

    >

    > 참고로 윈도우 2000에서는 아무런 반응도 없습니다.

    > 아래 소스처럼 처음 접속이 되면 접속을 시도한 클라이언트 IP를

    > 출력하도록 했는데 윈도우 2000에서는 반응이 없구요

    > NT 에서는 정상적으로 접속처리가 되는데 아래 과정에서 폼을 띄울때

    > 프로그램이 멈춰 버립니다.

    > 꼭 좀 알려주세요.

    >

    > procedure TMainForm.IdTCPServer1Connect(AThread: TIdPeerThread);

    > begin

    >

    > // 현재 대화를 요구한 사람의 IP를 얻는다.

    > ChatQueryIP := AThread.Connection.Binding.PeerIP;

    > // 확인하기 위해서 Message 창을 이용했습니다.

    > ShowMessage (ChatQueryIP);

    >

    > // 요구한 사람의 ID를 얻는다.

    > with LoginQuery do

    > begin

    > SQL.Clear;

    > DatabaseName :=DBName;

    > SQL.Add('SELECT * FROM LoginTable ');

    > SQL.Add('where IPaddress = :PARAMSTRING');

    > ParamByName('PARAMSTRING').AsString := ChatQueryIP;

    > Open;

    > if Eof = False then

    > begin

    > // ChatQueryName, ChatQueryID, ChatQueryIP 는 모두 전역 변수로 선언되어있슴.

    > ChatQueryName := FieldByName('UserName').AsString;

    > ChatQueryID := FieldByName('ID').AsString;

    > end

    > else

    > exit;

    > Close;

    > end;

    >

    > { // 처음에 이렇게 했다가 나중에 IdTCPServerExecute 함수 안에서 폼을 생성하도록 했습니다.

    > 모두다 창이 뜨면서 프로그램이 다운 됩니다.

    > ChatForm := TChatForm.Create(Self);

    > ChatForm.CaptionLabel.Caption := ' 1:1 채팅 [ ' + ChatQueryName + ':' + ChatQueryID + ' ]';

    > ChatForm.Left := MainForm.Left + 136;

    > ChatForm.Top := MainForm.Top + 60;

    > ConnectIP := ChatQueryIP;

    > ChatForm.Show;

    > }

    > end;

    >

    > procedure TMainForm.IdTCPServerExecute(AThread: TIdPeerThread);

    > var

    > ReceivePort, ReceiveName, ReceiveID: String;

    > begin

    > With AThread.Connection do

    > begin

    > // Client로 부터 사용할 포트 정보를 받는다.

    > // 정보를 순서대로 사용포트, 이름, ID로 넘겨 받는다.

    > ReceivePort := ReadLn;

    > ReceiveName := ReadLn;

    > ReceiveID := ReadLn;

    > // 정상적으로 받았는지 확인하기위한 message 창

    > ShowMessage(ReceiveString + #13+ #11 + ReceivePort + #13+ #11 + ReceiveName + #13+ #11 +ReceiveID);

    > end;

    > Disconnect;

    > end;

    >

    > // 아래 부분은 IdTCPServerConnect 함수에서 하던것을 이곳에서 처리하도록 했습니다.

    > // 이곳 역시 마찬가지로 폼이 생성되는 과정에서 프로그램이 다운됩니다.

    > ChatForm := TChatForm.Create(Self);

    > ChatForm.CaptionLabel.Caption := ' 1:1 채팅( ' + ReceiveName + ' )';

    > ChatForm.Left := MainForm.Left + 136;

    > ChatForm.Top := MainForm.Top + 60;

    >

    > ChatForm.ChatTCPClient.Host := ChatQueryIP;

    > ChatForm.ChatTCPClient.Port := StrToInt(ReceivePort);

    > ChatForm.ChatTCPServer.DefaultPort := StrToInt(ReceivePort);

    > ChatForm.ChatTCPServer.Active := True;

    > ChatForm.Show;

    >

    > end;

    >

    >

  • Profile
    델파이 완전초보자 2000.12.23 20:32
    답변 감사 합니다.

    많은 도움이 되었구요. 음...

    Synchronize 에 대해서 다시한번 공부하게 되었습니다.

    경문님 앞으로도 많은 도움 부탁 드립니다.





    이경문 wrote:

    > 일단 Connect부분만 수정해 보도록 하겠습니다.

    > Connect될때 처리되어야 할 코드를 ShowChatForm이라는 멤버 프로시져를 다음과 같이 만들구요, Connect되었을 때 Synchronize(ShowChatForm)해 주면 됩니다.

    > Execute에서도 마찬가지로 화면에 보여줘야 할 부분은 반드시 프로시져를 만들고 Synchronize해 주시기 바랍니다.

    >

    > procedure TMainForm.ShowChatForm;

    > begin

    > // 확인하기 위해서 Message 창을 이용했습니다.

    > ShowMessage (ChatQueryIP);

    > // 요구한 사람의 ID를 얻는다.

    > with LoginQuery do

    > begin

    > SQL.Clear;

    > DatabaseName :=DBName;

    > SQL.Add('SELECT * FROM LoginTable ');

    > SQL.Add('where IPaddress = :PARAMSTRING');

    > ParamByName('PARAMSTRING').AsString := ChatQueryIP;

    > Open;

    > if Eof = False then

    > begin

    > // ChatQueryName, ChatQueryID, ChatQueryIP 는 모두 전역 변수로 선언되어있슴.

    > ChatQueryName := FieldByName('UserName').AsString;

    > ChatQueryID := FieldByName('ID').AsString;

    > end

    > else

    > exit;

    > Close;

    > end;

    > ChatForm := TChatForm.Create(Self);

    > ChatForm.CaptionLabel.Caption := ' 1:1 채팅 [ ' + ChatQueryName + ':' + ChatQueryID + ' ]';

    > ChatForm.Left := MainForm.Left + 136;

    > ChatForm.Top := MainForm.Top + 60;

    > ConnectIP := ChatQueryIP;

    > ChatForm.Show;

    > end;

    >

    > procedure TMainForm.IdTCPServer1Connect(AThread: TIdPeerThread);

    > begin

    > // 현재 대화를 요구한 사람의 IP를 얻는다.

    > ChatQueryIP := AThread.Connection.Binding.PeerIP;

    > // 확인하기 위해서 Message 창을 이용했습니다.

    > Synchronize(ShowChatForm); <- ShowMessage 및 ChatForm을 띄우는 부분은 반드시 Synchronize해야 한다.

    >

    > end;

    >

    >

    >

    > 델파이 완전초보자 wrote:

    > > 답변 감사합니다.

    > > 제가 하고 있는 소스일부입니다. 지적해 주세요.

    > >

    > > 참고로 윈도우 2000에서는 아무런 반응도 없습니다.

    > > 아래 소스처럼 처음 접속이 되면 접속을 시도한 클라이언트 IP를

    > > 출력하도록 했는데 윈도우 2000에서는 반응이 없구요

    > > NT 에서는 정상적으로 접속처리가 되는데 아래 과정에서 폼을 띄울때

    > > 프로그램이 멈춰 버립니다.

    > > 꼭 좀 알려주세요.

    > >

    > > procedure TMainForm.IdTCPServer1Connect(AThread: TIdPeerThread);

    > > begin

    > >

    > > // 현재 대화를 요구한 사람의 IP를 얻는다.

    > > ChatQueryIP := AThread.Connection.Binding.PeerIP;

    > > // 확인하기 위해서 Message 창을 이용했습니다.

    > > ShowMessage (ChatQueryIP);

    > >

    > > // 요구한 사람의 ID를 얻는다.

    > > with LoginQuery do

    > > begin

    > > SQL.Clear;

    > > DatabaseName :=DBName;

    > > SQL.Add('SELECT * FROM LoginTable ');

    > > SQL.Add('where IPaddress = :PARAMSTRING');

    > > ParamByName('PARAMSTRING').AsString := ChatQueryIP;

    > > Open;

    > > if Eof = False then

    > > begin

    > > // ChatQueryName, ChatQueryID, ChatQueryIP 는 모두 전역 변수로 선언되어있슴.

    > > ChatQueryName := FieldByName('UserName').AsString;

    > > ChatQueryID := FieldByName('ID').AsString;

    > > end

    > > else

    > > exit;

    > > Close;

    > > end;

    > >

    > > { // 처음에 이렇게 했다가 나중에 IdTCPServerExecute 함수 안에서 폼을 생성하도록 했습니다.

    > > 모두다 창이 뜨면서 프로그램이 다운 됩니다.

    > > ChatForm := TChatForm.Create(Self);

    > > ChatForm.CaptionLabel.Caption := ' 1:1 채팅 [ ' + ChatQueryName + ':' + ChatQueryID + ' ]';

    > > ChatForm.Left := MainForm.Left + 136;

    > > ChatForm.Top := MainForm.Top + 60;

    > > ConnectIP := ChatQueryIP;

    > > ChatForm.Show;

    > > }

    > > end;

    > >

    > > procedure TMainForm.IdTCPServerExecute(AThread: TIdPeerThread);

    > > var

    > > ReceivePort, ReceiveName, ReceiveID: String;

    > > begin

    > > With AThread.Connection do

    > > begin

    > > // Client로 부터 사용할 포트 정보를 받는다.

    > > // 정보를 순서대로 사용포트, 이름, ID로 넘겨 받는다.

    > > ReceivePort := ReadLn;

    > > ReceiveName := ReadLn;

    > > ReceiveID := ReadLn;

    > > // 정상적으로 받았는지 확인하기위한 message 창

    > > ShowMessage(ReceiveString + #13+ #11 + ReceivePort + #13+ #11 + ReceiveName + #13+ #11 +ReceiveID);

    > > end;

    > > Disconnect;

    > > end;

    > >

    > > // 아래 부분은 IdTCPServerConnect 함수에서 하던것을 이곳에서 처리하도록 했습니다.

    > > // 이곳 역시 마찬가지로 폼이 생성되는 과정에서 프로그램이 다운됩니다.

    > > ChatForm := TChatForm.Create(Self);

    > > ChatForm.CaptionLabel.Caption := ' 1:1 채팅( ' + ReceiveName + ' )';

    > > ChatForm.Left := MainForm.Left + 136;

    > > ChatForm.Top := MainForm.Top + 60;

    > >

    > > ChatForm.ChatTCPClient.Host := ChatQueryIP;

    > > ChatForm.ChatTCPClient.Port := StrToInt(ReceivePort);

    > > ChatForm.ChatTCPServer.DefaultPort := StrToInt(ReceivePort);

    > > ChatForm.ChatTCPServer.Active := True;

    > > ChatForm.Show;

    > >

    > > end;

    > >

    > >