C#

[C#] 네트워크(Network)를 통한 클래스(Class) 직렬화(Serialize) 역직렬화(Deserialize)

SSABI 2019. 11. 5. 10:54
반응형

네트워크를 통해서 클래스를 직렬화 역직렬화 하는 방법으로 다음과 같은 방법을 사용했습니다.

서버

[Serializable]
public class Data
{
public int Num;
public string Name;
public Data() { }
public Data(int num, string name)
{
Num = num;
Name = name;
}
}
class Program
{
static void Main(string[] args)
{
List<Data> datas = new List<Data>()
{
new Data(1, "SSABI"),
new Data(2, "Simpson")
};
TcpListener tcpListener = new TcpListener(IPAddress.Any, 6000);
tcpListener.Start();
Console.WriteLine("Start Server");
while (true)
{
try
{
TcpClient tcpClient = tcpListener.AcceptTcpClient();
NetworkStream networkStream = tcpClient.GetStream();
MemoryStream memoryStream = new MemoryStream();
BinaryFormatter binaryFormatter = new BinaryFormatter();
// 접속 정보 확인
Socket clientSocket = tcpClient.Client;
IPEndPoint ipEndPoint = (IPEndPoint)clientSocket.RemoteEndPoint;
Console.WriteLine("Client IP : " + ipEndPoint.Address.ToString());
binaryFormatter.Serialize(memoryStream, datas);
byte[] length = BitConverter.GetBytes(memoryStream.Length);
byte[] byteArray = memoryStream.ToArray();
networkStream.Write(length, 0, 4);
networkStream.Write(byteArray, 0, byteArray.Length);
memoryStream.Close();
networkStream.Close();
tcpClient.Close();
}
catch (System.Exception e)
{
}
}
}
}
view raw Server.cs hosted with ❤ by GitHub

클라이언트

[Serializable]
public class Data
{
public int Num;
public string Name;
public Data() { }
public Data(int num, string name)
{
Num = num;
Name = name;
}
}
class Program
{
static void Main(string[] args)
{
TcpClient tcpClient = new TcpClient();
tcpClient.Connect("192.168.1.110", 6000);
NetworkStream networkStream = tcpClient.GetStream();
BinaryFormatter binaryFormatter = new BinaryFormatter();
byte[] lengthArray = new byte[4];
networkStream.Read(lengthArray, 0, lengthArray.Length);
int length = BitConverter.ToInt32(lengthArray, 0);
byte[] byteArray = new byte[length];
networkStream.Read(byteArray, 0, byteArray.Length);
MemoryStream memoryStream = new MemoryStream(byteArray);
memoryStream.Position = 0;
object obj = binaryFormatter.Deserialize(memoryStream);
List<Data> datas = (List<Data>)obj;
memoryStream.Close();
networkStream.Close();
tcpClient.Close();
}
}
view raw Client.cs hosted with ❤ by GitHub

 

하지만 위와 같은 방법으로 클래스를 직렬화 해서 역직렬화 했을 때

클라이언트쪽에서 다음과 같은 오류가 발생했습니다.

 

이 오류는 역직렬화 할때 클라이언트 쪽에서는 참조하는 어셈블리가 없기 때문에 클래스를 역직렬화 할 수가 없는 오류입니다. 같은 클래스를 정의해도 클라이언트 쪽에서는 어떤 클래스인지 인식할 수 없습니다. 오류를 해결하는 방법으로 DLL을 만들어서 어셈블리를 참조하는 방법으로 오류를 해결할 수도 있지만, 여기서는 Xml을 직렬화 한 후 역직렬화 하는 방식으로 설명드리겠습니다.

 

다음은 XmlSerializer 클래스를 이용한 클래스 직렬화 역직렬화를 방식입니다. NetworkStreamList<Data>를 직렬화 한 후 클라이언트 쪽에서 역직렬화를 하면 됩니다.

클래스의 변수는 반드시 public으로 지정해야 변수에 있는 값이 전달이 됩니다. 또한 직렬화하려는 클래스는 매개변수가 없는 생성자를 가지고 있어야 합니다.

서버

[Serializable]
public class Data
{
public int Num;
public string Name;
public Data() { }
public Data(int num, string name)
{
Num = num;
Name = name;
}
}
class Program
{
static void Main(string[] args)
{
List<Data> datas = new List<Data>()
{
new Data(1, "SSABI"),
new Data(2, "Simpson")
};
TcpListener tcpListener = new TcpListener(IPAddress.Any, 6000);
tcpListener.Start();
Console.WriteLine("Start Server");
while (true)
{
try
{
// XML 버전
TcpClient tcpClient = tcpListener.AcceptTcpClient();
NetworkStream networkStream = tcpClient.GetStream();
// 접속 정보 확인
Socket clientSocket = tcpClient.Client;
IPEndPoint ipEndPoint = (IPEndPoint)clientSocket.RemoteEndPoint;
Console.WriteLine("Client IP : " + ipEndPoint.Address.ToString());
XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<Data>));
xmlSerializer.Serialize(networkStream, datas);
networkStream.Close();
tcpClient.Close();
}
catch (System.Exception e)
{
}
}
}
}
view raw Server.cs hosted with ❤ by GitHub

클라이언트

[Serializable]
public class Data
{
public int Num;
public string Name;
public Data() { }
public Data(int num, string name)
{
Num = num;
Name = name;
}
}
class Program
{
static void Main(string[] args)
{
TcpClient tcpClient = new TcpClient();
tcpClient.Connect("127.0.0.1", 6000);
NetworkStream networkStream = tcpClient.GetStream();
XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<Data>));
List<Data> datas = (List<Data>)xmlSerializer.Deserialize(networkStream);
networkStream.Close();
tcpClient.Close();
foreach (Data data in datas)
Console.WriteLine(data.Num + ", " + data.Name);
}
}
view raw Client.cs hosted with ❤ by GitHub

 

Client 실행 결과

반응형