2014. 9. 28. 15:00

슈퍼소켓(SuperSocket)을 테스트 하다보니 예상하지 못한 문제가 몇 가지 있네요 ㅎㅎㅎㅎ

 

여러 문제 중 클라이언트에서는 데이터를 전송했는데 서버에서 반응이 없는 경우를 알아봅시다.

 

0. 문제의 확인

 

클라이언트에서 데이터를 보내 봅시다.

 

 

서버에서 접속되었다는 메시지가 잘 출력되는 것으로 보아 서버에 접속은 됐습니다.

그런데 메시지를 보내면(스크린 샷에서 '보내기'로 표시된 부분이 메시지를 보내는 부분입니다.) 서버에서 응답이 없습니다 ㅡ.ㅡ

(정상적인 동작이라면 서버로 보낸 메시지가 그대로 돌아와야 합니다.)

 

그래서 기존에 만들었던 서버로 테스트해보니 클라이언트에서 데이터는 잘 넘어오고 있습니다.

 

1. 문제의 이유

이런 문제가 발생하는 것은 슈퍼소켓의 기본리시브필터가 아스키(ASCII)로 된 텔넷 형식만 통과시키기 때문인듯합니다.

 

 

덕분에 필터를 거쳐 나온 데이터는 줄 바꿈 문자가 들어간 아스키코드인 경우에만 정확한 데이터가 나옵니다.

 

 

2. 간단한 해결 방법

일단 아스키코드를 사용 할 때는 줄 바꿈 문자가 와야 한다고 합니다.

(참고 : SuperSocket Discussions - Client connects, but server is not receiving messages)

 

 줄 구분자, 혹은 줄 바꿈 문자는

'\r\n'

를 이야기 합니다.

 

이제 클라이언트쪽에 줄 바꿈 문자를 붙여 보내 봅시다.

그러면 리시브필터를 통과하여 데이터가 오는 것을 확인 할 수 있습니다.

 

 

 

 

 

3. 근본적인 해결 방법

하지만!

아스키를 쓰지 않는다면 위방법은 쓸 수 없습니다.

 

결국 필터를 우리마음대로 수정해야 하는데.....

다행히 필터를 인터페이스라 재정의해서 쓰면 됩니다.

 

class claServerReceiveFilter : FixedHeaderReceiveFilter<BinaryRequestInfo>
{
	public claServerReceiveFilter()
		: base(6)
	{
	}
		
	protected override int GetBodyLengthFromHeader(byte[] header, int offset, int length)
	{
		return (int)header[offset + 4] * 256 + (int)header[offset + 5];
	}

	protected override BinaryRequestInfo ResolveRequestInfo(ArraySegment<byte> header, byte[] bodyBuffer, int offset, int length)
	{
		return new BinaryRequestInfo(Encoding.UTF8.GetString(header.Array, header.Offset, 4), bodyBuffer.CloneRange(offset, length));
	}

	/// <summary>
	/// 메시지가오면 여기에 걸린다.
	/// </summary>
	/// <param name="readBuffer"></param>
	/// <param name="offset"></param>
	/// <param name="length"></param>
	/// <param name="toBeCopied"></param>
	/// <param name="rest"></param>
	/// <returns></returns>
	public override BinaryRequestInfo Filter(byte[] readBuffer, int offset, int length, bool toBeCopied, out int rest)
	{
		rest = 0;

		//데이터가 있는지?
		if (null == readBuffer)
		{
			return NullRequestInfo;
		}

		//데이터가 있다.

		//리턴할 객체
		BinaryRequestInfo briReturn;
		//자른 데이터
		byte[] byteCutData = new byte[length];

		//데이터를 오프셋을 기준으로 자른다.
		Buffer.BlockCopy(readBuffer, offset, byteCutData, 0, length);

		//이 코드는 유니코드를 받기위한 것이므로 유니코로 테스트를 한다.
		briReturn = new BinaryRequestInfo(Encoding.Unicode.GetString(byteCutData)
											, byteCutData);

		return briReturn;
	}
}

 

 

위코드는 유니코드 처리를 위해 리시브 필터를 재정의(override)하는 것입니다.

 

 

 

 

 

이제 유니코드도 잘 돌아 갑니다.

 

 

마무리

그래도 다행인 것이 슈퍼소켓의 소스를 보면 필요하다 싶은 건 다 재정의가 가능하게 되어있습니다.

문제는 해당 코드를 찾는 게 힘들어서 그렇죠 ㅡ,.ㅡ;;