반응형

 

----------------------

Server Socket 작성 하기

----------------------

1. 소스 코드를 작성 하기 전에 우선 전체적인 코드를 개략적으로 이해 하기로 하자 .

우선 서버의 입장에서 로컬 종점을 생성 한다 . 리스닝을 위한 소켓을 열기 전에 로컬 종점 주소를 작성 해야 하며 서비스에 대한 종점을 생성 하기 위해 호스트의 IP 주소와 서비스의 포트 번호를 조합하여 TCP/IP 서비스의 고유 주소를 정의 한다 . Dns 클래스는 로컬네트워크 기기에서 지원하는 네트워크 주소에 대한 정보를 되돌려 주는 메소드를 제공 한다 . 로컬 네트워크 기기가 하나 이상의 네트워크 주소를 가지거나 로컬 시스템이 하나 이상의 네트워크 기기를 지원 한다면 Dns 클래스는 모든 네트워크 주소에 대한 정보를 되돌려 주며 애플리케이션은 아 배열에서 적절한 주소를 선택해야 한다 .

// 소켓에 사용할 종점을 설정

IPHostEntry ipHost = DNS.Resolve(“localhost”);

IPAddress ipAddr = ipHost.AddressList[0];

IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 11000);

2. 다음은 Socket 클래스의 새로운 인스턴스를 이용하여 스트림소켓을 생성 한다 . 이미 리스닝에 사용 할 로컬 종점을 작성 하였으므로 바로 소켓을 생성 할 수 있다 .

//TCP/IP 소켓을 생성

Socket sListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

AddressFamily 열거형은 Socket 인스턴스가 주소를 해석 하기 위해 사용하는 주소 스키마를 나타낸다 . 몇 가지 값들은 아래와 같다 .

AddressFamily.InterNetwork : IP 버전 4 주소

AddressFamily.InterNetwork V6: IP 버전 6 주소

AddressFamily.Ipx : IPX/SPX 주소

AddressFamily.NetBios: NetBios 주소

SocketType 은 TCP 와 UDP 소켓을 구분 하는데 이용 가능한 값은 아래와 같다 .

SocketType.Dgram : 데이터그램을 지원 , Dgram 은 Udp ProtocolType 과 AddressFamily.InterNetwork 와 함께 사용되어야 한다 .

SocketType.Raw : Raw Socket

SocketType.Stream : 스트림 소켓을 지원 , Stream 은 Tcp ProtocolType 과 AddressFamily.InterNetwork 와 함께 사용되어야 한다 .

세번째 파라미터 , 네번째 파라미터는 소켓에 필요한 프로토콜 형식을 정의 한다 . 그 값은 아래와 같다 .

Raw : Raw 패킷 프로토콜

Tcp : TCP

Udp : UDP

Ip : Internet Protocol

?  다음 단계는 Bind() 메소드를 사용하여 소켓에 이름을 부여 한다 . 생성자를 이용하여 소켓을 개방하면 소켓에 아무런 이름도 할강되어 있지 않다 . 즉 Bind() 메소드를 통해 소켓을 Local 종점에 연결 시키는 것이다 .

try {

sListener.Bind(ipEndPoint);

?  이제 소켓이 생성 되었고 , 이름이 바인딩 되었으므로 Listen() 을 사용하여 들어오는 연결에 대해 리스닝을 수행 할 수 있다 . 이때 파라미터에는 큐에 대기중인 연결의 최대 개수를 지정 한다 .

sListener.Listen(10);

?  위에서 리스닝을 했으므로 이젠 Accept() 를 이용하여 클라이언트의 연결을 수신하여 클라이언트와 서버의 이름 연결을 완료 한다 . Accept() 메소드는 대기중인 요청 큐로 부터 먼저 들어온 연결을 가지고 와 이를 처리할 새로운 소켓을 생성 한다 . 새로운 소켓이 생성 되었다고 하더라도 원래 소켓은 계속 리스닝을 수행 하므로 복수의 클라이언트 요청을 처리하기 위해서는 멀티쓰레드를 사용 한다 .

while(true) {

...

Socket handler = sListener.Accept();

?  Send(), Receive() 메소드를 이용하여 데이터를 보내고 , 받는다 .

string data = null;

while(true) {

byte[] bytes = new byte[1024];

// 클라이언트로부터 수신된 데이터

int byteRes = handler.Receive(byte);

// 바이트를 문자열로 변환

data += Encoding.Default.GetString(bytes, 0, byteRec);

// 메시지의 끝인지 확인

if (data.IndexOf(“”) > -1) {

break;

}

}

?  루프를 빠져 나온 후 클라이언트에게 응답을 돌려주기 위해 새로운 바이트 배열을 준비 한다 . 변환을 마친 후 Send() 메소드를 이용하여 데이터를 보내자

string theReply = “Thank you for those ” + data.Length.ToString() + “ characters …”;

byte[] msg = Encoding.Default.GetBytes(theReply);

handler.Send();

?  서버와 클라이언트의 데이터 교환이 끝나면 Close() 를 이용하여 소켓을 종료 한다 . 항상 Close() 를 하기 전에 Shutdown() 을 이용하여 남아 있는 데이터를 확실히 제거 하자 . 각 소켓 인스턴스 마다 Close() 메소드를 호출 해야 한다 .

handler.Shutdown(SocketShutdown.Both);

handler.Close();

SocketShutdown 값은 열거형으로 아래와 같은 값을 취한다 .

Both : 송 . 수신용 소켓 모두

Receive : 수신용

Send : 송신용 소켓

소스 코드는 아래와 같다 .[SocketServer.cs]

using System;

using System.Net.Sockets;

using System.Net;

using System.Text;

public class SocketServer

{

public static void Main (string [] args)

{

// establish the local end point for the socket

IPHostEntry ipHost = Dns.Resolve("localhost");

IPAddress ipAddr = ipHost.AddressList[0];

IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 11000);

// create a Tcp/Ip Socket

Socket sListener = new Socket(AddressFamily.InterNetwork,

SocketType.Stream, ProtocolType.Tcp);

// bind the socket to the local endpoint and

// listen to the incoming sockets

try

{

sListener.Bind(ipEndPoint);

sListener.Listen(10);

// Start listening for connections

while (true)

{

Console.WriteLine("Waiting for a connection on port {0}",ipEndPoint);

// program is suspended while waiting for an incoming connection

Socket handler = sListener.Accept();

string data = null;

// we got the client attempting to connect

while(true)

{

byte[] bytes = new byte[1024];

int bytesRec = handler.Receive(bytes);

data += Encoding.ASCII.GetString(bytes,0,bytesRec);

if (data.IndexOf("") > -1)

{

break;

}

}

// show the data on the console

Console.WriteLine("Text Received: {0}",data);

string theReply = "Thank you for those " + data.Length.ToString()

+ " characters...";

byte[] msg = Encoding.ASCII.GetBytes(theReply);

handler.Send(msg);

handler.Shutdown(SocketShutdown.Both);

handler.Close();

}

}

catch(Exception e)

{

Console.WriteLine(e.ToString());

}

} // end of Main

}

----------------------

Client Socket 작성 하기

----------------------

1. 클라이언트 코드가 서버와 다른 점은 Connect() 메소드 부분이다 . 이것은 클라이언트가 원격의 서버에 연결 하고자 할 때 사용하는 메소드 이다 . 사용하기 위해서는 우선 원격 종점을 설정 해야 한다 .

// 소켓에 사용할 원격 종점을 설정

IPHostEntry ipHost = DNS.Resolve(“127.0.0.1”);

IPAddress ipAddr = ipHost.AddressList[0];

IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 11000);

Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

sender.Connect(ipEndPoint);

Connect() 메소드로 소켓을 종점 파라미터로 지정된 원격 호스트와 연결을 맺는다 . 일단 연결이 이루어 지면 데이터를 보내고 받을 수 있다 .

string theMessage = “This is a test”;

byte[] msg = Encoding.Default.GetBytes(theMessage+””);

// 소켓을 이용하여 데이터를 보냄

int bytesSend = sender.Send(msg);

// 원격으로부터 ( 서버 ) 응답을 수신

int bytesRec = sender.Receive(bytes);

이젠 마지막으로 Shutdown() 을 호출하여 소켓을 해제 한다 . 그리고 Close() 하자

sender.Shutdown(SocketShutdown.Both);

sender.Close();

[ 아래는 SocketClient.cs 의 소스 파일 이다 .]

using System;

using System.Net.Sockets;

using System.Net;

using System.Text;

public class SocketClient

{

// If you specify any text as a command-line argument, it will be sent to the server.

// e.g. SocketClient "Send this text" will send that string

// If no command-line arguments are specified, a default string is sent

public static void Main (string [] args)

{

// data buffer for incoming data

byte[] bytes = new byte[1024];

// connect to a Remote device

try

{

// Establish the remote end point for the socket

IPHostEntry ipHost = Dns.Resolve("127.0.0.1");

IPAddress ipAddr = ipHost.AddressList[0];

IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 11000);

Socket sender = new Socket(AddressFamily.InterNetwork,

SocketType.Stream, ProtocolType.Tcp);

// Connect the socket to the remote endpoint. Catch any errors

sender.Connect(ipEndPoint);

Console.WriteLine("Socket connected to {0}",

sender.RemoteEndPoint.ToString());

//string theMessage=Console.ReadLine();

string theMessage;

if (args.Length==0)

theMessage = "This is a test";

else

theMessage = args[0];

byte[] msg = Encoding.ASCII.GetBytes(theMessage+"");

// Send the data through the socket

int bytesSent = sender.Send(msg);

// Receive the response from the remote device

int bytesRec = sender.Receive(bytes);

Console.WriteLine("The Server says : {0}",

Encoding.ASCII.GetString(bytes,0, bytesRec));

// Release the socket

sender.Shutdown(SocketShutdown.Both);

sender.Close();

}

catch(Exception e)

{

Console.WriteLine("Exception: {0}", e.ToString());

}

}

}

반응형

+ Recent posts