Poll() 메소드
보통 Receive() 명령과 같은 블로킹 네트워크 함수를 실행하고자 한다면,
이 명령어를 실행하기 전에 소켓을 확인할 수 있는 기능이 있어야 한다.
소켓 메소드 Poll() 바로 이런한 기능을 수행한다.
이 메소드는 소켓 객체를 확인하여 네트워크 메소드 콜이 블록을 거는지, 또는 성공적으로 완료 했는지를 확인한다.
Poll() 메소드의 형태는 다음과 같이 간단하다.
bool Poll(int microseconds, SelectMode mode);
Poll() 메소드는 간단한 boolean 값을 반환하는데,
수행하고자 하는 행동이 블록을 걸지 않고 완료할 수 있으면, true를, 블록을 걸면 false를 반환하다.
int 파라미터는 Poll() 메소드가 특정 이벤트에 대해서 소켓을 주시하는 시간을 microseconds 단위로 나타낸 것이다.
SelectMode 파라미터는 주시해야 할 행동을 나타낸다.
SelectMode 클래스는 Poll() 메소드가 모니터링할 세 개의 가능한 이벤트들을 수치화한 것이다.
namespace System.Net.Sockets
{
public enum SelectMode
{
SelectRead = 0,
SelectWrite = 1,
SelectError = 2
}
}
SelectRead
: SelectMode 클래스의 SelectRead 값을 사용할 경우, 다음과 같은 조건을 만족하면 Poll() 메소드가 true를 반환한다.
○ Accept() 메소드가 성공
○ 소켓에 읽어들일 데이터가 있을 때
○ 연결이 종료되었을 떄
SelectWrite
: SelectMode 클래스의 SelectWrite 값을 사용할 경우, 다음과 같은 조건을 만족하면 Poll() 메소드가 true를 반환한다.
○ Connect() 메소드가 성공했을 때
○ 소켓으로 데이터를 전송할 수 있을 때
SeletError
: SelectMode 클래스의 SelectError 값을 사용할 경우, 다음과 같은 조건을 만족하면 Poll() 메소드가 true를 반환한다.
○ Connect() 메소드가 실패했을 때
○ 대역 외 데이터가 있는데 소켓의 OutOfBandInline 속성이 설정되지 않았을 때
설정된 SelectMode 값에 대해서
Poll() 메소드가 반환하는 값을 참고하여 소켓에 블로킹 함수를 실행할지 여부를 판단할 수 있다.
result = sock.Poll(1000000, SelectMode.SelectRead);
소켓 객체 sock는 1백만 microsecond(1초) 동안 확인하여 소켓에 데이터가 있는지를 판단한다. 반환값이 true이면, Receive() 메소드는 블로킹 없이 완료할 수 있다는 뜻이다.
예제 )
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace TcpPollServer
{
class TcpPollServer
{
static void Main(string[] args)
{
int recv;
byte[] data = new byte[1024];
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9050);
Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
newsock.Bind(ipep);
newsock.Listen(10);
Console.WriteLine("Waiting for a client...");
bool result;
int i = 0;
while (true)
{
i++;
Console.WriteLine("polling for accept#{0}...", i);
result = newsock.Poll(1000000, SelectMode.SelectRead);
if (result)
{
break;
}
}
Socket client = newsock.Accept();
IPEndPoint newclient = (IPEndPoint)client.RemoteEndPoint;
Console.WriteLine("Connected with {0} at port {1}", newclient.Address, newclient.Port);
string welcome = "Welcome to my test server";
data = Encoding.ASCII.GetBytes(welcome);
client.Send(data, data.Length, SocketFlags.None);
i = 0;
while (true)
{
Console.WriteLine("polling for recieve #{0}...", i);
i++;
result = client.Poll(3000000, SelectMode.SelectRead);
if (result)
{
data = new byte[1024];
i = 0;
recv = client.Receive(data);
if (recv == 0)
{
break;
}
Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));
client.Send(data, recv, 0);
}
}
Console.WriteLine("Disconnected from {0}", newclient.Address);
client.Close();
newsock.Close();
}
}
}
테스트 클라이언트 : SimpleTcpClient.cs
여기에서는 while() 루프를 돌면서 SelectRead 속성에 대해서 소켓을 점검한다.
SelectRead 속성이 설정되어 있으면 Poll() 메소드는 true 값을 반환한다.
이 때 들어오는 연결 요청이 있기 때문에 Accept() 메소드를 블로킹없이 안전하게 호출할 수 있다.
Poll() 메소드는 1초에 한번씩 확인하도록 설정되어 있다.
Poll() 메소드 호출 중간 중간에 프로그램은 다른 메소드를 호출하는 등 여러 기능들을 수행할 수 있다.
이 프로그램은 단순히 카운터를 증가시키면서 콘솔에 표시하여 프로그램이 폴링 중에도 실행된다는 것을 보여준다.
들어오는 연결 요청을 수락하여 연결이 확립되면,
또 하나의 폴링 루프가 생성되어 Receive() 메소드에 대해서 들어오는 데이터를 대기한다.
이 때에도 역시 Poll() 메소드 호출 중간에 프로그램은 다른 필요한 오퍼레이션을 실행할 수 있다.
'[ Programing ] > Server' 카테고리의 다른 글
TCP Packet Max Size - About 65K (0) | 2020.07.20 |
---|---|
Fiddler 패킷 캡처... (0) | 2020.06.01 |
동기화와 비동기화 방식 (0) | 2013.11.03 |
윈도우 소켓 SOCKET WSAAPI socket() 사용시 리턴 소켓 넘버 값 관련 (0) | 2013.10.25 |
윈도우 소켓 WSAStartup, WSACleanup (0) | 2013.10.25 |