정보를 찾아보니 3rd 파티에서 iocp를 구현한 라이브러리를 판다고는 하는데.. 

nio를 이용해 만드는 것도 나쁘진 않다고함. 관건은.. iocp나 eventSelect처럼 소켓 디바이스에 입력이 있었을때
자동으로 호출되는 콜백 메서드 등을 찾아야함. 

패키지를 살짝 살펴본 결과.. 일반 소켓(net.socket)을 통한 스트림 연결이 아닌, nio를 지원하는 소켓 스트림이
있는듯함. java.nio.SocketChannel , ServerSocketChannel , 글고 이벤트 발송자 역할인 Selector 인가도 있음.
(SocketChannel , ServerSocketChannel 클래스는 구독자 + SelectionKey 클래스는 발송자,구독자를 느슨하게
 연결하는 adapter 클래스)
(java.nio 패키지와 그 하위 패키지들을 대충 확인할 필요가 있음)


하여간 1.스트림 열고 2.읽고,쓰고 3.닫고 할줄 알면.. 채팅 프로그램 만들수 있을거라 착각중;;(선생님께서 나중에 
4단계?에서 채팅프로그램 만든다고 하셧으니.. 미리 진행)

****************************************************************************
내 채팅 프로그램의 기획을 어떻게 할까를 결정해야함.

1. 몇대몇 채팅 프로그램 (1:1? 다자간?)
      a. 여러명이 하나의 채널에서 모여서 채팅할수 있는 프로그램인지?
      b. 1:1로 채팅하는 프로그램인지?
2. 서버의 역할 (peer to peer? broad cast server?)
       a.서버의 역할이 클라와 클라를 중계해주는 개념인지(클라a가 메세지 보내면 그것을 연결된 다른 b,c,d 클라한테 쏴주는 
          역할
       b.방장의 개념으로 방을 만들고 접속을 받아 들이는 클라인지(클라겸 서버) 

요즘 인기있는 카톡은 어떤식이지? 카톡에 로그인해서 방을 만들면 사람들이 들어오는건가?(방장이 서버역할, 서버는 개설된
방정보를 클라에게 전달후, 클라가 방을 선택하면 연결시켜주기)  vs 아니면.. 1:1로 문자 메세지 보내는건가? 중간에 사람들
이 들어올수도 있고..

흠.. 1 = a  , 2 = a (조금 어려울라나;;)

대략적인 스케치

<클라>
1.데이터
 a.유저: 별명
 b.서버 접속용 정보:서버주소,포트번호,채팅방번호(원하는 사람끼리 채팅가능하게 구분해주는 개념)
 c.i/o용 데이터:소켓,입력 스트림, 출력 스트림
                     내가 쓴 메세지&채팅 참여자가 쓴 메세지를 담아서 출력할 byte 버퍼,
                     유저의 입력을 저장할 스캐너
2.동작
  a.채팅방에 찾아간다.
  b.사람들과 채팅을 한다.(유저로부터 쓴다.쓴 내용을 서버에 보낸다. 서버로부터 읽는다. 읽은 내용을 화면에 출력한다 = i/o)
  c.채팅을 종료한다.

처음 입장시 보낸 데이터 패킷:아이피는 알아서 전달 될테니.. 별명,선택한 방 -> 자신의 방에서 놀면됨 
채팅시 보낼 데이터 패킷: 유저형 별명 + 채팅 메세지 (선택한 방은 불필요.. 근데.. 나중에 전체 공지를 추가하려면?)
=>메세지 타입 만들어야 겠음.
enum MsgType
{LOGIN,CHAT,LOGOUT};

=>한번 더 쪼개야 겠음;;
enum ChatType
{NORMAL};

=> 그럼으로 데이터 패킷은: 메세지 타입 + 종류따라 채팅 메세지, 기타등등
=> 서버측에선 메세지를 처리하는 메서드를 커맨드 패턴으로 만들어 보자 -_-;;


(실제 채팅처럼 로그인 처리=인증 , 주고 받는 데이터 암호화, java.awt나 swing을 이용해 gui로 만드는건.. 
너무 복잡해지고 능력도 안됨;;)

<서버>

1.데이터
  a.유저 데이터 리스트(채팅방의 개념) 여러개의 채팅방을 지원할거면 유저 리스트의 리스트
     유저 데이터 = url,port, 방번호(리스트의 인덱스)
  b.
2.동작
  a.유저가 1번 방에 접속한다. (1번 유저리스트에 유저 추가)
  b.유저가 채팅 메세지를 보냈다. (1번 유저리스트에게 메세지 전부 보내기)
  c.유저가 1번 방에서 채팅을 종료했다. (1번 유저리스트에서 해당 유저 삭제)
    여기서 고려할께.. 중간 삽입,삭제가 잦아지면.. 연결리스트 고려할 필요가 있음..(문제는 조회가 느림)
  d.... 서버가 할일이 없네.. 욕설 쓰면 강퇴 시낄까 , 아니면 귓속말 기능을 추가할까;;
    방장 개념을 만들어서 방장에게 강퇴 권한을 줄까.. 괜히 복잡해지겠다. 심플하고 유연하게 만들어보자.
    나중에 기능 추가가 쉽도록!

만들어보자 -_-;;

****************************************************************

내가 채팅 프로그램 만들때 필요한 클래스들.. (nio 중심으로)

<클라용>

java.nio.channels 
클래스 SocketChannel


스트림형 접속 소켓용의 선택 가능 채널입니다.

소켓 채널은, 접속 네트워크 소켓의 완전한 추상화가 아닙니다. 소켓 옵션의 바인드, 종료, 및 조작은,socket 메소드 호출에 의해 취득한 관련 Socket객체를 개입시켜 실시할 필요가 있습니다. 임의의 기존 소켓의 채널을 작성하거나 소켓 채널에 관련한 소켓으로 SocketImpl 객체를 사용하도록(듯이) 지정할 수 없습니다.

소켓 채널은, 이 클래스의 open 메소드중 1 개(살)을 호출하는 것에 의해 작성할 수 있습니다. 새롭게 작성된 소켓 채널은 오픈입니다만, 접속은 확립되어 있지 않습니다. 미접속의 채널에 대해서 입력 조작을 호출하려고 하면(자),NotYetConnectedException 가 throw 됩니다. 소켓 채널을 접속하려면 , 그 connect 메소드를 호출합니다. 접속된 소켓 채널은, 클로즈 할 때까지 접속된 채로 있습니다. 소켓 채널이 접속되고 있을지 어떨지는,isConnected 메소드의 호출에 의해 판단할 수 있습니다.

소켓 채널은 「비블록 접속」을 지원합니다. 소켓 채널의 작성과 원격 소켓에의 링크의 확립 프로세스는 connect 메소드에 의해 개시되어 나중에finishConnect 메소드에 의해 완료합니다. 접속 조작이 실행중일지 어떨지는,isConnectionPending 메소드의 호출에 의해 판단할 수 있습니다.

소켓 채널의 입력측과 출력측은, 실제로 채널을 클로즈 하는 일 없이, 따로 따로 「정지」됩니다.관련 소켓 객체의 shutdownInput 메소드를 호출해 채널의 입력측을 정지한 뒤, 한층 더 채널을 읽어내려고 하면(자), 스트림의 마지막을 나타내는 -1 이 돌려주어집니다. 관련 소켓 객체의 shutdownOutput메소드를 호출해 채널의 출력측을 정지한 뒤, 한층 더 채널에 기입하려고 하면(자),ClosedChannelException 가 throw 됩니다.

소켓 채널은,Channel 클래스로 지정되고 있는 비동기 클로즈 조작과 자주(잘) 닮은 「비동기 정지」를 지원합니다. 한편의 thread가 소켓의 채널에 대한 read 조작의 도중에 블록 되고 있는데, 이제(벌써) 한편의 thread가 소켓의 입력측을 정지했을 경우, 블록 된 thread의 read 조작은, 바이트를 일절 읽어내는 일 없이 종료해,-1 를 돌려줍니다. 한편의 thread가 소켓의 채널에 대한 기입 조작의 도중에 블록 되고 있는데, 이제(벌써) 한편의 thread가 소켓의 출력측을 정지했을 경우, 블록 된 thread는 AsynchronousCloseException 를 받습니다.

소켓 채널은, 복수의 병행 thread로 안전하게 사용할 수 있습니다데이터 그램 채널은 병행 read 및 기입을 지원합니다. 다만, read를 실시하는 thread도 기입을 실시하는 thread도 특정의 시점에서는 항상 1 개 이하입니다connect 메소드와 finishConnect 메소드는 서로 동기 하고 있어, 어느 쪽인지 한편의 메소드의 호출중에 읽어들여 또는 기입해 조작을 개시하려고 하면(자), 이 처리는 최초의 호출이 완료할 때까지 블록 됩니다.


=>명세 요약

1.소켓 채널 생성하려면 open() 사용

2.알아서 connect()

3.비동기 i/o

4.스레드 사용 가능



static SocketChannelopen (SocketAddress  remote) 
          소켓 채널을 오픈해, 원격 주소에 접속합니다.

longread (ByteBuffer [] dsts) 
          이 채널의 바이트 순서가 지정된 버퍼에 읽어들입니다.

longwrite (ByteBuffer [] srcs) 
          이 채널의 바이트 순서가 지정된 버퍼로부터 써냅니다.



클래스 java.nio.channels.spi. AbstractSelectableChannel 로부터 상속된 메소드
blockingLock , configureBlocking , implCloseChannel , implCloseSelectableChannel , implConfigureBlocking , isBlocking , isRegistered , keyFor ,provider , register
 
클래스 java.nio.channels. SelectableChannel 로부터 상속된 메소드
register
 
클래스 java.nio.channels.spi. AbstractInterruptibleChannel 로부터 상속된 메소드
begin , close , end , isOpen
 
클래스 java.lang. Object 로부터 상속된 메소드
clone , equals , finalize , getClass , hashCode , notify , notifyAll , toString , wait , wait , wait
 
인터페이스 java.nio.channels. Channel 로부터 상속된 메소드
close , isOpen



<서버용>


java.nio.channels 
클래스 ServerSocketChannel


by givingsheart 2014. 1. 1. 16:20