public Socket (AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType );Socket 객체의 생성자는 세가지 열거형 AddressFamily, SocketType, ProtocolType을 인자로 받으며 각 열거형은 모두 System.Net.Sockets 네임 스페이스에 정의되어 있다. AddressFamily 열거형은 Socket 객체가 주소를 풀이하기 위해 사용하는 주소 지정 스키마를 정의하며, 여기서는 인터넷을 사용하는 소켓 응용 프로그램을 작성하므로 AddressFamily.InterNetwork를 사용한다.
Socket mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);생성자에 전달할 수 있는 인자로는 세 가지 읽기 전용 속성은 AddressFamily, SocketType, ProtocolType이 있다.
public void Connect( EndPoint remoteEP);Connect() 메소드 인자는 System.Net.EndPoint 클래스의 인스턴스이며, EndPoint 클래스는 추상 클래스로 네트워크 주소를 의미한다. EndPoint 클래스의 하위 클래스는 System.Net.IPEndPoint이다. Connect() 메소드를 사용할 때는 연결하려는 원격 서버의 IP 주소와 포트 번호를 포함한 IPEndPoint 객체를 인자로 사용해야 한다. 소켓에서 원격 서버에 연결하기 위해 IPEndPoint 객체를 어떻게 구성할 수 있을까? IPEndPoint 클래스 정의를 살펴보면 두 가지 생성자가 있다.
public IPEndPoint(long address, int port); public IPEndPoint(IPAddress address, int port);일반적으로 129.36.129.44와 같이 IP 주소를 인자로 표현하는 두 번째 생성자를 자주 사용한다. 다음에 보게 될 것처럼 닷넷 소켓 프로그래밍에서는 long형의 주소를 사용하는 표기법 보다 IP 주소를 사용하는 것이 더 쉽다. 첫번째 생성자가 원격지 IP 주소를 long 형으로 사용하고, 두 번째 생성자가 System.Net.IPAddress 객체를 사용하는 것을 제외하면 두 생성자 모두 큰 차이점은 없다. 어떤 생성자를 선택하든 간에 원격 서버의 IP 주소와 포트 번호를 알고 있어야 하며, 대부분의 잘 알려진 서비스들은 할당된 기본 포트 번호가 있기 때문에 포트 번호는 별 문제가 되지 않는다. 예를 들어 HTTP는 80번, 텔넷은 25번, FTP는 21번 포트를 사용한다. IP 주소는 일반적으로 직접 사용하지 않는다. 왜냐하면 Microsoft.com 또는 oreillynet.com과 같이 IP 주소를 대신하는 도메인 이름을 기억하는 것이 IP 주소를 기억하는 것 보다 훨씬 쉽기 때문이다. 따라서 연결할 원격 서버의 IP 주소를 알아내기 위해 먼저 도메인 이름을 IP 주소로 변환해야 한다. 원격 서버 연결에 사용할 IPAddress 클래스의 인스턴스를 얻기 위해서는 System.Net.Dns와 System.Net.IPHostEntry 클래스를 사용한다. 인터넷 도메인 네임 시스템(DNS, Domain Name System)에서 특정 호스트에 관한 정보를 가져오기 위해 사용하는 클래스이므로 클래스 이름은 Dns 클래스이며, 도메인 네임에 대한 IP 주소들을 가져오기 위해 Dns 클래스의 Resolve() 메소드를 사용한다. Resolve() 메소드는 IP 주소들의 배열을 갖는 IPHostEntry 객체를 반환하며 IP 주소들의 배열을 가져오는데에는 IPHostEntry 클래스의 AddressList 속성을 사용한다. 예를 들어, 다음 코드는 DNS 이름에 해당하는 모든 IP 주소를 표시한다.
using System.Net.Sockets; using System.Net; try { String server = "microsoft.com"; // or any other domain name IPHostEntry hostEntry = Dns.Resolve(server); IPAddress[] ipAddresses = hostEntry.AddressList; Console.WriteLine(server + " is mapped to:"); foreach (IPAddress ipAddress in ipAddresses) { Console.WriteLine(ipAddress.ToString()); } } catch (Exception e) { Console.WriteLine(e.ToString()); }위 코드를 실행하면 DNS 이름(여기서는 Microsoft.com)에 해당하는 모든 IP 주소들을 표시한다. DNS 이름에 하나 이상의 IP가 연결되어 있다면 이에 해당하는 모든 IP가 표시될 것이다. DNS 이름에 하나 이상의 IP가 있더라도 사람들은 첫번째 IP만을 사용한다. 이와 같이 첫번째 IP를 이용하는 이유는 보통 DNS 이름이 하나의 IP 주소에만 연결되어 있기 때문이다. DNS 이름에 연결된 첫번째 IP 주소를 가져오려면 다음 코드를 사용해야 한다.
HostEntry.AddressList[0]IPAddress 객체를 얻어왔으면 이제 원격 서버에 연결하는 데 필요한 IPEndPoint 객체를 구성할 수 있다. 연결에 성공하면 Socket 인스턴스의 Connected 속성이 true로 설정된다. 서버 응용 프로그램은 일정 시간이 지나고 나면, 연결을 닫도록 되어 있기 때문에 프로그래머는 소켓 인스턴스를 사용하여 어떤 작업을 시작하기 전에 Connected 속성을 사용해 연결을 확인할 수 있다. 소켓을 이용한 작업이 끝난 후에는 연결을 명시적으로 닫기 위해 Close() 메소드를 사용한다. 보통은 수신된 모든 데이터를 비우고 Close() 메소드를 호출하는 Shutdown() 메소드를 사용하는 것이 좋다.
참고 도서 .NET Framework Essentials, 3rd Edition |
public int Send(byte[] buffer);buffer에 전송하길 원하는 데이터를 포함한 바이트 배열을 저장한다. 이 오버로드된 버전을 사용하여 버퍼에 있는 모든 데이터를 전송할 수 있다. 두 번째 오버로드는 버퍼에 있는 모든 데이터를 전송할 수 있고, System.Net.Sockets.SocketFlags 열거형을 사용할 수 있으며 비트 연산을 사용하여 여러 값을 조합할 수 있다. 메소드 서명은 다음과 같다.
public int Send(byte[] buffer, SocketFlags socketFlags);세 번째 오버로드된 버전은 버퍼에 있는 데이터를 모두 혹은 일부분만 전송할 수 있으며 SocketFlags 열거형을 사용한다.
public int Send( byte[] buffer, int size, SocketFlags socketFlags );위 오버로드된 버전에서 size는 전송할 바이트 수를 의미한다. 마지막 오버로드 버전은 세 번째 오버로드된 버전과 비슷하지만 전송할 데이터의 시작위치를 지정하기 위해 옵셋 위치를 지정할 수 있다. 메소드 서명은 다음과 같다.
public int Send( byte[] buffer, int offset, int size, SocketFlags socketFlags );이 오버로드에서 offset은 옵셋 위치이다. 데이터를 동기적으로 받아오기 위해서는 Receive() 메소드를 사용한다. 이 메소드는 4가지 오버로드된 버전이 있으며 Send() 메소드의 오버로드된 버전과 비슷하다. 오버로드된 버전의 서명은 다음과 같다.
public int Receive(byte[] buffer); public int Receive(byte[] buffer, SocketFlags socketFlags); public int Receive( byte[] buffer, int size, SocketFlags socketFlags ); public int Receive( byte[] buffer, int offset, int size, SocketFlags socketFlags );Receive() 메소드를 사용할 때 수신된 데이터의 크기와 데이터를 읽어들일 수 있는지 확인하기 위해 Socket 클래스의 Available 속성을 사용할 수 있다.
이전 글 : RSS에 대한 이런 저런 이야기
다음 글 : 닷넷, 인터페이스 이해하기
최신 콘텐츠