java

[자바] nio 를 이용한 소켓 서버부분 (GUI 연동)

sieunju 2017. 4. 16. 00:48
반응형


안녕하세요 nio 를 이용한 자바 소켓 서버부분에 대해서 포스팅을 해보도록 하겠습니다.

전 아직 "학생"이기 때문에 10년? 15년? 도 더 된 기능을 가지고 하는거라 너무 질타는 하지 말아주시길 바랍니다.ㅜㅜ 나중엔  AsynchronousServerSocketChannel (비동기) 에 대해서도 공부할 계획입니다!! :D  




우선 서버 부분 캡처 사진입니다.

Accept IP 부분은 클라이언트가 접속한 Channel 의 정보이고,

RecvIP 부분은 어떠한 클라이언트가 데이터를 주고받는지에 대해서 알려주는 부분이 되겠습니다.


그럼 소스를 보도록 하겠습니다.

소스를 보기전에 이소스는 제가 열심히 공부하면서 손수 작성하게된 소스이므로, 마음껏 사용하셔도 되지만,

이름은 변경하지 말아주시길 바랍니다.

(또한, 이러한 기능이 있었으면 좋겠다 또는, 안되는 부분은 바로바로 댓글로 피드백 해주시길 바랍니다 :D)



제가 만든 자바 서버의 기능으로는

1. 원하는 상대에게 보내기

2. 자기자신에게 보내기

3. 접속한 모든 클라이언트에게 보내기

4. 연결 해제


이러한 기능들이 있습니다.


그럼 소스 해석을 해보도록 하겠습니다.


1.run() 메소드



 이부분을 한마디로 정의하면 서버를 실행시키고 그 서버에 대한 SelectionKey 의 값은 "접속가능한 상태" 로 설정한다. 라고 알고계시면 되겠습니다.



서버에서 가장 중요하다고 생각되는 부분이 이부분인데요

이부분에서 "keys" 라는 변수가 핵심인데요,

클라이언트가 서버한테 접속할려고 할때에는 key 값이 Accept 가능상태입니다. 좀더 이해하기 쉽게

중단점을 걸어서 보여드리도록 하겠습니다.




이렇게 보시게 되면 처음에 클라이언트는 Accept 상태가 true 이고 Read 상태는 false 입니다. 왜냐하면

Accept 를 넘어간후, 그다음에 데이터를 받을수있는 Read 상태로 넘어가야 하기 때문에 처음에 클라이언트가 서버에 접속했을때에는 Accept 가 true로 되어야 합니다.


만약에 데이터를 보냈을 경우에는


위 사진과 같이 Accept 는 false 이고, Read 는 true 상태가 되어서 데이터를 읽기 시작합니다.


2. Accept 메소드



이메소드 같은 경우에는 말그대로 클라이언트가 서버로 접속된것들을 처리해주는 메소드라고 보시면 되겠습니다.


여기서 유심히 보아야 할부분은

channel.configureBlocking(false) 인데요

이부분은 자바 nio 에만 있는 기능입니다. (근데 nio 가 non-blocking 이 아닌거 같습니다. 즉, 비동기가 아니란 셈이죠. 지극히 제생각엔 말이죠..)


추가적으로 여기서 _Selector 에서 접속한 클라이언트를 등록을 해줍니다.


3.ReadPacket 메소드




이 메소드는 클라이언트로 부터 받은 데이터를 읽어내는 부분이 되겠습니다.

딱히....그렇게 중요해보이는 소스는 없어서 다음으로 넘어갑니다.


4. RecvEvt 메소드



이부분은 데이터를 받은 부분을 처리해주는 메소드가 되겠습니다.


여기서 중요한 부분은 this._Buf.flip() 메서드인데요.

ByteBuffer 를 사용하실때에는

1 . flip()

2. clear()

3. rewind()


이 3가지가 가장 중요하다고 생각이 듭니다.


차례로 한마디로 설명하면 flip 은 position 값을 0 으로 이동

rewind 은 데이터를 재사용할때 사용합니다. (거의 초기화라고 보시면 됩니다.)

clear() 모든 값들을 깔끔히 정리합니다.


이렇게 해서 데이터를 받으면 그의 맞게 처리를 합니다.


저같은 경우에는 패킷(서버&클라)에서 데이터를 보낼때



_Type 

(2byte)

dataSize 

 (4byte)

 

 

 data

 (...)

 

 



이런식으로 구성했습니다. 처음에 어떠한 타입인지 인식후

데이터사이즈 + 데이터 이런식으로 구성되어있습니다.

(처음에는 앞에 전체 사이즈를 주면서 했는데 자바는 굳이 그렇게 할 필요가 없어서 맨앞에는 그냥 타입부터 설정하도록 하였습니다.)


5.Send 메소드



이 부분은 클라한테 보내는 메소드중 하나입니다. 말그대로 key 값을 가진 클라이언트한테 보내는 역활입니다.

이걸로 원하는 상대나 자기자신한테 보낼수 있습니다.


6.SendAll 메소드




이 메소드는 말그대로 접속된 클라이언트한테 전체적으로 데이터를 전송 역활을 합니다.

중간중간에 주석처리 되어있어서 굳이 설명할필요는 없을거 같습니다.

한마디로 정리하자면 _Selector 에 저장되어 있는 서버개설자와 클라이언트들을 Iterator 통하여 나열한후,

서버개설자인 (Accept 값이 true 인 key값)를 제외하고 나머지에게 데이터를 전송합니다.


7.RecvSend 메소드



이 메소드는 제가 귓속말기능 (원하는 상대에게 데이터를 보내는 기능) 을 구현하다가 만들게 되었는데요,

그냥 Send 랑 별반 다를게 없어보이지만, 또한 굳이 이걸 안만들어도 될듯싶었지만, 구분을 지어야 한다는 생각에

만들었습니다.

이유는 Server 에 A,B,C 클라이언트가 접속되어 있습니다.

그후, A클라이언트가 B클라이언트한테 데이터를 보내면 데이터는 그대로 전송이 되지만, A클라이언트가 먹통이 되는 현상이 걸리더군요 ㅡㅡ;

그래서 저는  A클라이언트가 데이터를 보냈는데 그이후에 데이터를 안받아서 그런거 같다고 중단점과 실험을 통해서 알게 되었습니다.  그래서 원하는 상대에게 데이터를 보낼때, 즉, A가 B한테 데이터를 보낼때 서버는 A->B 에게 데이터를 보내고 A->A 한테도 아무데이터를 보내는 것이 되겠습니다.

저도 이게 왜그런지는 잘모르겠지만, 아무쪼록 이러한 현상이 나와서 저런식으로 구현해서 해결을 하였습니다.

차차 공부하다보면 알게 되겠지만, 알다가도 모르는 문제인거 같습니다 _-_;;;


이후로는 그렇게 중요한 메소드라기보단, 부수적으로 필요한 기능 메소드라서 생략하도록 하겠습니다.


##제가 설명이 좀 많이 부족하지만, 궁금하시는 부분에서 댓글을 남겨주시면 친절히 답변해드리도록 하겠습니다.

조만간 클라이언트와 패킷 소스에 대해서도 포스팅하겠습니다.(시험기간 끝나고....어휴)


이상 포스팅을 마치도록 하겠습니다.

감사합니다.




반응형