[C#] System.Byte[]

Jaemoon Lee·2022년 9월 28일
0

[C샾]

목록 보기
3/13

20220928

소켓통신 구현 중... 비슷한 메시지 Send/Recv 함수를 이용함에도...
클라이언트와의 송수신 메시지는 로그 상 정상출력 되지만,
서버와의 송수신 메시지는 로그 상 System.Byte[]라고만 출력되는.. 기현상이 발생하였다.


처음에는 Log Write 부분에 Encoding이 좀 이상해서 기능상 문제는 없고, 출력만 잘 못 되는줄 알기도 했고...
테스트로 쓰는 서버 프로그램이 이상한줄 알았는데
결론은 내 프로그램이 이상한 것으로 보인다.

public void SendMessage(string value)
{
	byte[] buff = Encoding.ASCII.GetBytes(value);
	cmdStream.Write(buff, 0, buff.Length);
	Store.getInstance().twLog.WriteLog("[핀체크->Server] " + buff.ToString());
}

일단 서버를 향한 SendMessage 함수는 이렇게 구성되어 있는데...

public void Send(String data)  //소켓 통신: 프로그램에 메시지 보내는 부분
{
	try
	{
		// Convert the string data to byte data using ASCII encoding.  
		byte[] byteData = Encoding.ASCII.GetBytes(data);

		// Begin sending the data to the remote device.  
		if (Handler != null)
		{
			Handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), Handler);
			Store.getInstance().twLog.WriteLog("[핀체크->Client] : " + data);
		}
	}
	catch (Exception)
	{
	}
}

웃긴건 클라이언트를 향한 SendMessage 함수의 구성도 크게 다를게 없다는 것이다... (얘는 정상)

이런 저런 방법을 시도해보던 중 String to Byte / Byte to String 에 관한 네이버 블로그 포스팅 글을 발견하였다...
https://blog.naver.com/hursh1225/40120911491

byte[] data에 string 값을 저장해놓고

Console.WriteLine( data )
또는 Console.WriteLine( data.ToString() )으로 백날 찍어봐야

System.Byte[] 라는 놈만 찍힌다.


환장한다 ㅋㅋㅋㅋ


원인은 C#의 byte[]는 오브젝트이기 때문에 형변환이 불가능하기 때문이라고 한다.

해결법은 System.Text.Encoding 클래스를 사용하면 된다.



1. String을 byte[]로 변환

String str1 = "Hello World!";

// Default 대신 Unicode, UTF8, UTF16, UTF32 등 사용 가능

byte[] ba = System.Text.Encoding.Default.GetBytes( str );



2. byte[]를 String으로 변환

String str2 = System.Text.Encoding.Default.GetString( ba );



3. 출력

Console.WriteLine( "{0}", str1 ); // "Hello World!"

Console.WriteLine( "{0}", ba ); // "System.Byte[]"

Console.WriteLine( "{0}", ba.ToString() ); // "System.Byte[]"

Console.WriteLine( "{0}", System.Text.Encoding.Default.GetString( ba ) ); // "Hello World!"
Console.WriteLine( "{0}", str2 ); // "Hello World!"

선지자께서 작성하신 고대 문헌에 따르면 C#의 바이트 배열은 그 자체가 오브젝트이기 때문에 원래 형변환이 불가능하나,
Encoding 클래스를 통해 변환하는 방법이 있다고 한다.
(물론 내 프로그램의 기존 함수에도 적용되어있지만, 자세히 읽어보니 그 사용방법이 잘 못 되었던 것이다.)

올바른 SendMessage 함수

// 프로그램이 send하는 value라는 String값을 buff라는 바이트로 형변환 한다.
byte[] buff = Encoding.ASCII.GetBytes(value);
cmdStream.Write(buff, 0, buff.Length);
// 어차피 로그에 남길 메시지니까, 형변환이 아닌 기존의 String형인 value를 넣으면 정상 출력 된다...
Store.getInstance().twLog.WriteLog("[핀체크->Server] " + ㅍvalue);


정상적으로 서버를 향해 메시지가 간 것을 확인할 수 있다.

올바른 RecvMessage 함수

public void ReceiveCommand()
{
	//서버로부터 오는 메시지를 담을 바이트형 버퍼 선언
	byte[] msg = new byte[1024];
	int msgLength = 0;
	msgLength = cmdStream.Read(msg, 0, msg.Length);
	// 버퍼를 String으로 형변환 하기 위한 인코딩 함수 사용.
	Store.getInstance().twLog.WriteLog("[Server->핀체크] " + Encoding.Default.GetString(msg));


어.. 뭔가 이상하긴 하지만 일단 데이터가 내가 원하는 String형으로 들어오는 것을 확인할 수 있다.

나머지는 내일 계속......

20221014 추가 ...

String To Byte 뿐만 아니라...
ToString() 을 통한 String 변환 함수도 사용하고 있다.

reg.GetValue("SERVERIP").ToString()

이 코드는 SERVERIP라는 레지스트리 키에 저장된... 형태가 불분명한 문자를 ToString 함수를 통해 무조건 String으로 변환할 수 있도록 한 것이다.

그럼 반대로 String을 int로 변환해야할 때가 있지 않을까?
→ 있더라.. 이 프로그램에서 IP 변수는 String형을 가지지만, Port는 int형을 고정으로 가진다. (그냥 통신 Connect 함수의 반환형이 그렇다. 어쩔 수 없다. 받아드려야한다. 찾아보면 방법이 있긴 하겠지만 그냥 이게 더 편할 것이다.)

int sockPort;

Int32.TryParse(((MainWindow)System.Windows.Application.Current.MainWindow).reg.GetValue("SERVERPORT").ToString(), out sockPort);

Int32의 TryParse를 통해 SERVERPORT 레지스트리 키값으로 저장된 데이터를 int형으로 반환하는 코드이다.
이때 함수는 끝에 "out 변수" 로 int 형을 반환해야하므로 반환값을 담을 정수형 지역변수나 전역변수를 입력해주도록 하자.

profile
초보개발세발자

0개의 댓글