Q&A

  • <조언부탁합니다> 서버와 클라언트 소켓에서 특정 클라이언트 에게만 메시지 보내기?


안녕하세요.



저는 여기에서 많은 자료를 참고 하고 있고 조언도 많이 얻었습니다.



다시한번 조언 부탁 드립니다.



제가 서버소켓과 클라이언트 소켓을 따로 써서, 서버에 클라이언트가 접속을



하도록 하였습니다. 그러다가 서버에 접속된 클라이언트 중에 어떤 특정 클라이언



트에게만 메시지를 보내야 되는데 어떤 방법이 있는지 모르겠습니다.



조언 부탁합니다. (단, 서버측에서만 코딩을 한다면, 예를 들어 IP 주소나 혹은



'ServerSocket1.Socket.Connections[i]'과 같은 것을 사용해서 특정인에게만



보낼수 없습니까? )

4  COMMENTS
  • Profile
    김영습 2000.07.11 10:21
    홍기원 wrote:

    >

    > 안녕하세요.

    >

    > 저는 여기에서 많은 자료를 참고 하고 있고 조언도 많이 얻었습니다.

    >

    > 다시한번 조언 부탁 드립니다.

    >

    > 제가 서버소켓과 클라이언트 소켓을 따로 써서, 서버에 클라이언트가 접속을

    >

    > 하도록 하였습니다. 그러다가 서버에 접속된 클라이언트 중에 어떤 특정 클라이언

    >

    > 트에게만 메시지를 보내야 되는데 어떤 방법이 있는지 모르겠습니다.

    >

    > 조언 부탁합니다. (단, 서버측에서만 코딩을 한다면, 예를 들어 IP 주소나 혹은

    >

    > 'ServerSocket1.Socket.Connections[i]'과 같은 것을 사용해서 특정인에게만

    >

    > 보낼수 없습니까? )



    위의 답변들이 너무 잘되어 있어서 뭐라 적기가 그러네요...^^

    제가 한 방법을 적어놓고 갈렵니다.



    첫번째 할일: 클라이언트가 접속할때 (서버의 connection 이벤트) 마다 리스트박스 하나 올려놓구

    선 접속하는 놈 마다 ip를 받아놓는다.

    listbox1.Items.Add(socket.RemoteAddress);



    두번째 할일: 접속한놈 에게 메세지 보내기 ^^

    물론, 접속자가 서버에 무언가를 요청해야 겠죠..(서버의 clientread 이벤트일때)

    우선

    var

    i : integer;

    begin

    // 일단 변수 i에다가 접속한 놈의 ip를 받아서리....

    i :=listbox1.Items.IndexOf(socket.RemoteAddress);

    serversocket1.Socket.Connections[i].SendText('멜롱');

    // 이렇게 하면.. 리스트 박스에서 socket.RemoteAddress 했는 놈의

    인덱스를 가지고와서리.. 보내는 겁니다.

    테스트 해보시면 알겁니다.





    그럼...

  • Profile
    구창민 2000.07.08 01:51
    홍기원 wrote:

    >

    > 안녕하세요.

    >

    > 저는 여기에서 많은 자료를 참고 하고 있고 조언도 많이 얻었습니다.

    >

    > 다시한번 조언 부탁 드립니다.

    >

    > 제가 서버소켓과 클라이언트 소켓을 따로 써서, 서버에 클라이언트가 접속을

    >

    > 하도록 하였습니다. 그러다가 서버에 접속된 클라이언트 중에 어떤 특정 클라이언

    >

    > 트에게만 메시지를 보내야 되는데 어떤 방법이 있는지 모르겠습니다.

    >

    > 조언 부탁합니다. (단, 서버측에서만 코딩을 한다면, 예를 들어 IP 주소나 혹은

    >

    > 'ServerSocket1.Socket.Connections[i]'과 같은 것을 사용해서 특정인에게만

    >

    > 보낼수 없습니까? )





    안녕하세요~ 구창민입니다.



    많은 방법이 있습니다.



    구지 특정 IP에게로만 보내고 싶다면 약간의 편법을 동원하셔야 합니다.



    ServerSocket의 Socket객체의 메소드에 아래와 같은 것들이 있습니다.



    LocalHost

    LocalAddress

    LocalPort

    RemoteHost

    RemoteAddress

    RemotePort



    이넘들을 자알 이용하시면 원하시는 것을 구현할수 있는데요.



    Client 들이 Connect될시에 즉, ServerSocket의 OnClientConnected 이벤트 핸들러에

    StringList 같은 객체로 접속하는 Client들을 목록으로 구성해두시고,

    첨자값을 이용하여 그 Client들이 어떤넘들인지 레코드를 구성하는 겁니다.

    그러니까, 아이디와 첨자(인덱스)를 만들어 기록해 두는거죠.



    그러면 원하실때 그 첨자와 아이디를 비교하여 메세지를 보내고 싶은

    Client의 첨자와 아이디로 RemoteAddress를 비교해보시면 찾을수 있습니다.



    그럼~ 즐거운 프로그래밍 하시길~~~



    참, 델파이 코리아의 강좌란에 가셔서 통신강좌를 받아보세요.

    제가 말씀드린 내용을 그대로 적용시키기 아주 좋은 강좌입니다.



  • Profile
    임형호 2000.07.08 00:13
    홍기원 wrote:

    >

    > 안녕하세요.

    >

    > 저는 여기에서 많은 자료를 참고 하고 있고 조언도 많이 얻었습니다.

    >

    > 다시한번 조언 부탁 드립니다.

    >

    > 제가 서버소켓과 클라이언트 소켓을 따로 써서, 서버에 클라이언트가 접속을

    >

    > 하도록 하였습니다. 그러다가 서버에 접속된 클라이언트 중에 어떤 특정 클라이언

    >

    > 트에게만 메시지를 보내야 되는데 어떤 방법이 있는지 모르겠습니다.

    >

    > 조언 부탁합니다. (단, 서버측에서만 코딩을 한다면, 예를 들어 IP 주소나 혹은

    >

    > 'ServerSocket1.Socket.Connections[i]'과 같은 것을 사용해서 특정인에게만

    >

    > 보낼수 없습니까? )



    답변드리기가 좀 망설여집니다. 왜냐면.... 저도 전에 소켓으로 특정클라이언트에게 메세지를 보내려고 시도를 했었거든요. 그런데.... 접속한 클라이언트의 ip로 보내는 부분은 찾지를 못했습니다. 클라이언트의 ip는 알수있지만 ip로 특정클라이언트에게 보내는 부분은 잘 모르겠더라구요. 그래서 저 같은 경우에는 ServerSocket1.Socket.Connections[i] 명령어를 사용했습니다.

    제가 알기로는 Connections[i]에서 i값은 클라이언트의 접속순서로 알고있는데요.

    그래서 클라이언트에서 서버로 접속할때 서버에 listbox를 놓고 해당클라이언트가 접속할때 클라이언트에서 서버로 접속정보(ip나 컴퓨터이름)을 보냅니다. 서버에서는 listbox에 접속한 클라이언트의 ip나 컴퓨터이름등을 저장시켜놓고서 해당클라이언트로 보낼때는 가령 listbox에서 보낼 클라이언트의 item을 선택을 하고 메세지를 보냈습니다.

    그럴경우 listbox에 생성되는 item의 itemindex와 Connections[i]의 i 와는 같은 번호가 되거든요.

    즉 만약 listbox의 3번째 아이템을 선택했다면...그것은 서버로 접속한 3번째 클라이언트가 되고 그것의 itemindex는 2가 됩니다. 그러면 ServerSocket1.Socket.Connections[현재선택된 listbox의 itemindx]로 설정하시면 선택한 클라이언트로 메세지를 보낼수있습니다.

    좀 무식한 방법이지만 이런식으로 구성을 해서 해당 클라이언트로 메세지를 보냈습니다.

    잘 이해가 되셨는지 모르겠네요. 그런데 문제는 임의의 클라이언트가 접속해제될때마다 서버로 정보를 보내서 listbox에서 삭제해야되고, 음..이것까지야 별 문제가 아닌데요. 큰문제는 클라이언트 프로그램이 정상적으로 종료가 되지않을경우에는 미처 종료메세지를 보내지 못해서 에러가 발생합니다.

    전에 어떤분께서 질문을 올리셨던걸 기억하는데요. 위의 방법이 아니더라도 일반적으로 클라이언트가 비정상적으로 종료되면 서버쪽에서는 에러가 무조건 발생하는것 같더라구요. 아닌가?

  • Profile
    영호 2000.07.14 10:17
    "즉 만약 listbox의 3번째 아이템을 선택했다면...그것은 서버로 접속한 3번째 클라이언트가 되고 그것의 itemindex는 2가 됩니다. 그러면 ServerSocket1.Socket.Connections[현재선택된 listbox의 itemindx]로 설정하시면 선택한 클라이언트로 메세지를 보낼수있습니다. "라고 임형호씨가 답변해 주셨습니다.

    그런데 제가 궁금한거요?



    만약에 2번째에 연결되어 있는 클라이언트가 예상치 못한 오류를 일으켰을때요 예를 들어 클라이언트가 실행되고 있는 컴퓨터가 정전이 일어나 갑자기 다운이 돼었을 경우나 메모리가 부족해서 갑자기 다운이 되었을 경우나 선로에 이상이 있어서 접속이 끊어졌을 경우는 서버측에 메시지를 전송하지 못하고 다운이 발생되었기 때문에 서버측에서도 클라이언트의 접속이 끊겼는지 미처 확인을 하지 못해서 처리를 하지 못해 server.Socket.ActiveConnections의 수는 줄었는데 listbox에 2번째 아이템이 그대로 남아 있다면 어떻게 되겠습니까?

    3번째 있는 유저부터는 한나씩 밀려서 전송이 될거같은데 이 문제는 어떻게 하시려는지 궁금하군요

    물론 서버 소켓의 error 이벤트에 Socket.Close;를 해주고 ClientDisconnect이벤트에 접속이 끊긴 사용자의 socket.handle값으로 처리를 해주면 이 문제는 어느 정도 해결이 되지만 완전한 해결방편이 되지는 못하는 걸로 알고 있슴다.

    그래서 제가 하고 싶은 말은 ServerSocket1.Socket.connection[index]이라는 무식한 방법을 사용하지 않고 특정 클라이언트에 보내는 방법이 있을거 같은데요? 방법을 알고 있는 고수님 께서는 방법을 갈쳐주시면 고맙겠습니다.