2009-12-07 5 views
0

WCF를 사용하여 메시지 프레임을 구현하는 방법을 이해하려고합니다. 목표는 Tcp를 통해 독점 형식을 처리 할 수있는 WCF의 서버를 만드는 것입니다. 나는 SOAP를 위해서만 있기 때문에 net.Tcp 바인딩을 사용할 수 없다.WCF : 메시지 프레이밍 및 사용자 지정 채널

형식의 메시지를 수신하는 맞춤 채널을 작성해야합니다. 메시지 예는 "5 abcde"입니다. 특히 맞춤 채널에서 프레이밍하는 방법을 잘 모르겠습니다. 여기

몇 가지 샘플 코드

class CustomChannel: IDuplexSessionChannel 
{ 
private class PendingRead 
{ 
    public NetworkStream Stream = null; 
    public byte[] Buffer = null; 
    public bool IsReading = false; 
} 

private CommunicationState state = CommunicationState.Closed; 
private TcpClient tcpClient = null; 
private MessageEncoder encoder = null; 
private BufferManager bufferManager = null; 
private TransportBindingElement bindingElement = null; 
private Uri uri = null; 
private PendingRead pendingRead; 

public CustomChannel(Uri uri, TransportBindingElement bindingElement, MessageEncoderFactory encoderFactory, BufferManager bufferManager, TcpClient tcpClient) 
{ 
    this.uri = uri; 
    this.bindingElement = bindingElement; 
    this.tcpClient = tcpClient; 
    this.bufferManager = bufferManager;  
    state = CommunicationState.Created; 
    } 

public IAsyncResult BeginTryReceive(TimeSpan timeout, AsyncCallback callback, object state) 
{ 
    if (this.state != CommunicationState.Opened) return null; 

    byte[] buffer = bufferManager.TakeBuffer(tcpClient.Available); 
    NetworkStream stream = tcpClient.GetStream(); 
    pendingRead = new PendingRead { Stream = stream, Buffer = buffer, IsReading = true }; 
    IAsyncResult result = stream.BeginRead(buffer, 0, buffer.Length, callback, state); 
    return result; 
} 
public bool EndTryReceive(IAsyncResult result, out Message message) 
{ 
    int byteCount = tcpClient.Client.EndReceive(result); 
    string content = Encoding.ASCII.GetString(pendingRead.buffer) 

    // framing logic here 

    Message.CreateMessage(...) 
} 

}

그래서 기본적으로 EndTryReceive 주위에 처음으로 그냥 보류중인 읽기 버퍼 "5 AB"에서 메시지의 조각을 얻을 수있다. 그런 다음 두 번째로 메시지의 나머지 부분을 얻을 수 있습니다. 문제는 EndTryReceive가 처음 호출 될 때, Message 객체를 생성해야하는 경우입니다. 이는 부분 메시지가 채널 스택 위로 올라가는 것을 의미합니다.

내가 정말로하고 싶은 것은 EndTryReceive에서 메시지를 작성할 때 전체 메시지라는 것을 확인하기 위해 버퍼에 내 전체 메시지 "5 abcde"가 있는지 확인하는 것입니다.

누구나 WCF를 사용하여 사용자 지정 프레이밍을 수행하는 방법에 대한 예가 있습니까?

감사, 와이어 수준에서 바딤

답변

3

프레임은 WCF 채널 모델은 정말에 대한 관심 것이 아닙니다; 그것을 처리하는 것은 당신에게 달려 있습니다.

내가 말하고자하는 것은 귀하의 전송 채널이 수신시 전체 메시지를 반환하는 것은 귀하의 책임이라는 것입니다 (스트리밍은 조금 있지만 포인트까지만 변경됨).

귀하의 경우 채널 수신 작업을 기본 소켓의 수신 작업으로 직접 변환하는 것으로 보입니다. 그렇게하지 않으면 자신의 프레이밍을 시행 할 기회가 없기 때문입니다 규칙.

채널에서 하나의 수신 작업은 기본 소켓에서 둘 이상의 수신 작업으로 변환 될 수 있으며 괜찮습니다. (그리고 모든 비동기 작업을 수행 할 수 있으므로 영향을 줄 필요가 없습니다. 그 부분).

기본적으로 질문은 다음과 같습니다. 프로토콜 프레이밍 모델은 어떤 모양입니까? 여기에 와일드,하지만 메시지 길이가 접두사로, 길이가 10 진수 문자열로 인코딩 된 것 같습니다? (짜증나 보인다).

이 경우 가장 좋은 방법은 전송 버퍼에 들어오는 데이터 (예 : 최대 64KB의 데이터 또는 기타)를 저장 한 다음 각 수신 작업에서 버퍼를 검사하여 충분한 바이트가 있는지 확인하는 것입니다. 들어오는 메시지의 길이를 추출하십시오. 그렇다면 버퍼에서 필요한만큼의 바이트를 읽거나 버퍼를 비우고 소켓에서 많은 바이트를 읽으십시오. 프로토콜이 어떻게 작동하는지에 따라 실제로 필요하기 전에 부분 메시지를 읽는 것으로 끝날지도 모른다고 가정 할 때주의해야합니다.

0

나는 thomasr에 동의합니다. Microsoft 기술 샘플 "ChunkingChannel"에서 몇 가지 기본적인 아이디어를 얻을 수 있습니다.