2014년 2월 5일 수요일

[C# IO]C#에서의 TCP 소켓 Blocking 방식의 Server/Client 확인

어둠이 가라앉고 가시기까지 즉, BREAK OF DAWN이 찾아올 시간이 머지않다.

개발자는 코드로 이야기한다고 하였다. 바로 코드를 보고 이해를 시도한다. 어수선하나 이해 바란다.

본 글에서는 Blocking 통신에서의 특징을 언급하기 위한 목적성이 매우 강하므로 코드를 전부 일일이 잡아내어 상세히 설명하지 않았음을 밝힌다. 어느정도 유추가 가능하되 당장 크게 중요치 않은 부분은 약술하거나 생략하였음에 이해를 부탁드린다.

먼저 반드시 System.Net 이름공간과 System.Net.Sockets 이름공간을 사용한다고 명시하여야 한다.

using System.Net;
using System.Net.Sockets;

그렇지 않으면 에러가 뜰 것이다.

[그림 1] static 선언은 넘어가 주시면 감사하겠습니다. 늦게 보고 수정을 못 했습니다.

 [그림 1]을 살펴보자. 보통 이렇게 무언인가를 보자고 하였을 때의 반응은 두 가지이다. 그림에 글자가 있다면 다 일일이 읽어보는 반응과 그렇지 않는 반응이다. 전자로 반응을 예상하고 글을 작성한다.

 아마 [그림 1]을 이해하기 위해 [그림 2]가 필요할 것이다.
[그림 2] Main 메서드

 Socket의 생성자가 [그림 1]에서 확인되었다. linux에서나 Windows에서나 소켓 프로그래밍을 해본 경험이 있다면 전혀 어렵지 않게 그 용도와 의미를 파악할 수 있다.


client = new Socket( AddressFamily.InterNetwork , SocketType.Stream, ProtocolType.Tcp);
 첫번째 인자 : IPv4 프로토콜을 이용하여 통신하겠다고 지정하는 부분이다. 다른 상수값을 살펴보면 IPv6을 포함하여 여러가지 방식이 존재한다.
 두번째 인자 : 연결지향형 통신을 수행할 것인지(STREAM), 비연결지향형 통신을 수행할 것인지(DATAGRAM) 지정한다. 통상 STREAM이 사용되되 현 지구에서는 이것은 대개 TCP이다. 물론 여기서의 TCP는 절대 Team Crazy Performance가 아님을 밝혀 둔다.
 세번째 인자 : 통신을 통해 사용할 실제 프로토콜을 지정하는 부분이다. 여기서는 TCP를 사용한다. 이 지정 이유는 같은 통신을 이용하더라도 그 전송 방식에 두 가지 이상이 있을 경우 이를 확정하기 위함에 있다.

 나머지는 유추가 가능하다. 주석을 보고 확인하길 바란다.
IPAddress ipAddr = IPAddress. Parse(addr);
 // 문자열로 된 아이피 주소를 IPAddress 클래스로 변환하여 인스턴스를 생성한다.
IPEndPoint serverEndPoint = new IPEndPoint(ipAddr , port);
 // IPEndPoint는 말단 단말을 나타내기 위한 것으로 여기에서는 서버 정보를 나타내기 위해 쓰였다.
client.Connect (serverEndPoint);
 // 서버 정보를 담고 있는 IPEndPoint로 연결을 시도한다.
Console.WriteLine ("Connected to server...");
 // 문자열을 출력한다.

[그림 3] 주석이 안 보이네요..

   string inputMsg = Console.ReadLine();
  //inputMsg에 표준입력으로부터 입력받은 문자열을 받아 넣는다.
  byte[] bytesBuff = Encoding. UTF8.GetBytes (inputMsg);
  //유니코드8을 통해 문자열을 바이트로 변환한다.
  client.Send (bytesBuff, 0, bytesBuff.Length , SocketFlags.None);
  //변환한 바이트 배열을 전송한다. 4번째 인자인 SocketFlag는 비트 조합을 어떻게 할지를 지정하는데 쓰이며 종류로는 라우팅을 하지 않는다라든지 나누어 전송한다든지 등의 정보가 상수로 지정되어 있다.

[그림 4] 왜 주석이 안 보일까 의문을 갖습니다.

 client. Receive(bytesBuff , 0 , bytesBuff. Length , SocketFlags. None);
 //while문 밑에 Receive: 데이터 받아온다. 참고로 C#에서 소켓은 데이터를 바이트로 주고 받는다.
 String msg = Encoding.UTF8.GetString(bytesBuff, 0, byteBytesRecvd);
 //String msg 부분 : 바이트로 전달된 값을 UTP8 인코딩을 통해 문자열로 변환한다.

이상이다.

 클라이언트는 서버에 정보를 보내고 받는 아주 간단한 기능을 수행하고 있다.

다음은 서버다. 편의상 코드로 대체한다.

[그림 5] 서버 코드



  실행하면 절대 클라이언트가 데이터를 보내기 전까지 서버의 코드 흐름이 진행되지 않는 것을 확인할 수 있다.

[그림 6] 클라이언트 화면

[그림 7] 서버 화면

  데이터는 0.2초씩 지연되며 도착했으며 클라이언트 또한 모든 데이터를 수신하기 전까지 흐름이 중단되어 종료되지 않았음을 알 수 있었다.

  제가 주고받은 데이터에는 오타가 있습니다.

댓글 없음:

댓글 쓰기