RPC와 같은 여러 분산 기술 측면에서 "마샬링"이라는 용어가 사용되지만 직렬화와 어떻게 다른지 이해하지 못합니다. 둘 다 객체를 일련의 비트로 변환하지 않습니까?
RPC와 같은 여러 분산 기술 측면에서 "마샬링"이라는 용어가 사용되지만 직렬화와 어떻게 다른지 이해하지 못합니다. 둘 다 객체를 일련의 비트로 변환하지 않습니까?
답변:
마샬링 및 직렬화는 원격 프로 시저 호출의 맥락에서 느슨하게 동의하지만 의도적으로 의미 상 다릅니다.
특히, 마샬링은 여기에서 거기로 매개 변수를 가져 오는 것이지만 직렬화는 구조화 된 데이터를 바이트 스트림과 같은 기본 형식으로 복사하거나 복사하는 것에 관한 것입니다. 이러한 의미에서 직렬화는 마샬링을 수행하는 수단 중 하나이며 일반적으로 값별 의미를 구현합니다.
객체가 참조에 의해 마샬링 될 수도 있으며,이 경우 "와이어상의"데이터는 단순히 원래 객체에 대한 위치 정보이다. 그러나 이러한 개체는 여전히 직렬화를 중요하게 생각할 수 있습니다.
@Bill이 언급했듯이 코드 기반 위치 또는 객체 구현 코드와 같은 추가 메타 데이터가있을 수 있습니다.
I
필요에 따라 주요 , 대문자 변경 등으로 장식 하십시오.
둘 다 공통적으로 한 가지 일을합니다-그것은 객체를 직렬화 하는 것입니다. 직렬화는 객체를 전송하거나 저장하는 데 사용됩니다. 그러나:
직렬화는 마샬링의 일부입니다.
CodeBase 는이 객체의 구현을 찾을 수있는 곳의 Object 수신자에게 알려주는 정보입니다. 이전에 보지 못한 다른 프로그램으로 객체를 전달할 수 있다고 생각하는 프로그램은 코드베이스를 설정해야 코드를 로컬에서 사용할 수없는 경우 수신자가 코드를 다운로드 할 위치를 알 수 있습니다. 수신자는 객체를 직렬화 해제 할 때 객체에서 코드베이스를 가져와 해당 위치에서 코드를로드합니다.
invokeAndWait
및 Forms를 참조하십시오 Invoke
.
the implementation of this object
? 당신은 특정의 예를 줄 수 Serialization
와 Marshalling
?
로부터 마샬링 (컴퓨터 과학) Wikipedia 기사 :
"marshal"이라는 용어는 Python 표준 라이브러리에서 "serialize"와 동의어로 간주됩니다 1 되지만 Java 관련 RFC 2713에서는 동의어가 아닙니다.
객체를 "마샬링"한다는 것은 마샬링 된 객체가 "비 마샬링"될 때 객체의 클래스 정의를 자동으로로드하여 원래 객체의 사본을 얻는 방식으로 상태 및 코드베이스를 기록하는 것을 의미합니다. 직렬화 가능하거나 원격 인 모든 오브젝트를 마샬링 할 수 있습니다. 마샬링은 코드베이스를 기록한다는 점을 제외하면 직렬화와 비슷합니다. 마샬링은 마샬링이 원격 객체를 특별히 처리한다는 점에서 직렬화와 다릅니다. (RFC 2713)
객체를 "직렬화"한다는 것은 바이트 스트림이 객체의 복사본으로 다시 변환 될 수있는 방식으로 상태를 바이트 스트림으로 변환하는 것을 의미합니다.
따라서 마샬링 은 객체 의 코드베이스 를 상태 외에도 바이트 스트림에 저장합니다 .
주요 차이점은 Marshalling이 코드베이스와 관련이 있다고 생각합니다. 즉, 객체를 다른 클래스의 상태와 동등한 인스턴스로 마샬링 및 마샬링 해제 할 수 없습니다. .
직렬화는 객체가 다른 클래스의 인스턴스 인 경우에도 객체를 저장하고 동등한 상태를 다시 얻을 수 있음을 의미합니다.
즉, 일반적으로 동의어입니다.
마샬링 은 다른 환경 / 시스템에서 데이터가 표현되는 방식을 컴파일러에 알리는 규칙입니다. 예를 들어;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string cAlternateFileName;
두 개의 다른 문자열 값이 다른 값 유형으로 표시되는 것을 볼 수 있습니다.
직렬화 는 표현이 아닌 객체 내용 만 변환하고 (동일하게 유지됨) 직렬화 규칙을 준수합니다 (내보낼 항목 또는없는 항목). 예를 들어 개인 값은 직렬화되지 않으며 공개 값은 yes이며 개체 구조는 동일하게 유지됩니다.
다음은 더 구체적인 예입니다.
직렬화 예 :
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef struct {
char value[11];
} SerializedInt32;
SerializedInt32 SerializeInt32(int32_t x)
{
SerializedInt32 result;
itoa(x, result.value, 10);
return result;
}
int32_t DeserializeInt32(SerializedInt32 x)
{
int32_t result;
result = atoi(x.value);
return result;
}
int main(int argc, char **argv)
{
int x;
SerializedInt32 data;
int32_t result;
x = -268435455;
data = SerializeInt32(x);
result = DeserializeInt32(data);
printf("x = %s.\n", data.value);
return result;
}
직렬화에서 데이터는 나중에 저장 및 전개 해제 할 수있는 방식으로 전개됩니다.
마샬링 데모 :
(MarshalDemoLib.cpp)
#include <iostream>
#include <string>
extern "C"
__declspec(dllexport)
void *StdCoutStdString(void *s)
{
std::string *str = (std::string *)s;
std::cout << *str;
}
extern "C"
__declspec(dllexport)
void *MarshalCStringToStdString(char *s)
{
std::string *str(new std::string(s));
std::cout << "string was successfully constructed.\n";
return str;
}
extern "C"
__declspec(dllexport)
void DestroyStdString(void *s)
{
std::string *str((std::string *)s);
delete str;
std::cout << "string was successfully destroyed.\n";
}
(MarshalDemo.c)
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int argc, char **argv)
{
void *myStdString;
LoadLibrary("MarshalDemoLib");
myStdString = ((void *(*)(char *))GetProcAddress (
GetModuleHandleA("MarshalDemoLib"),
"MarshalCStringToStdString"
))("Hello, World!\n");
((void (*)(void *))GetProcAddress (
GetModuleHandleA("MarshalDemoLib"),
"StdCoutStdString"
))(myStdString);
((void (*)(void *))GetProcAddress (
GetModuleHandleA("MarshalDemoLib"),
"DestroyStdString"
))(myStdString);
}
마샬링에서 데이터를 반드시 평면화 할 필요는 없지만 다른 대체 표현으로 변환해야합니다. 모든 캐스팅이 마샬링되지만 모든 마샬링이 캐스팅은 아닙니다.
마샬링에는 동적 할당이 필요하지 않으며 구조체 간의 변환 일 수도 있습니다. 예를 들어, 페어가있을 수 있지만이 함수는 페어의 첫 번째 요소와 두 번째 요소가 다른 방식 일 것으로 예상합니다. fst와 snd가 뒤집어지기 때문에 한 쌍을 다른 쌍으로 캐스팅 / memcpy하면 작업을 수행하지 않습니다.
#include <stdio.h>
typedef struct {
int fst;
int snd;
} pair1;
typedef struct {
int snd;
int fst;
} pair2;
void pair2_dump(pair2 p)
{
printf("%d %d\n", p.fst, p.snd);
}
pair2 marshal_pair1_to_pair2(pair1 p)
{
pair2 result;
result.fst = p.fst;
result.snd = p.snd;
return result;
}
pair1 given = {3, 7};
int main(int argc, char **argv)
{
pair2_dump(marshal_pair1_to_pair2(given));
return 0;
}
마샬링의 개념은 여러 유형의 태그가 지정된 조합을 처리 할 때 특히 중요합니다. 예를 들어, "c 문자열"을 인쇄하기 위해 JavaScript 엔진을 얻는 것이 어려울 수 있지만 랩핑 된 c 문자열을 인쇄하도록 요청할 수 있습니다. 또는 Lua 또는 Python 런타임의 JavaScript 런타임에서 문자열을 인쇄하려는 경우. 그것들은 모두 문자열이지만 종종 마샬링하지 않고는 어울리지 않습니다.
최근에 JScript 배열이 C #에 "__ComObject"로 마샬링되어이 개체를 재생할 수있는 문서화 된 방법이 없었습니다. 나는 그것이 어디에 있는지에 대한 주소를 찾을 수 있지만, 나는 그것에 대해 다른 것을 전혀 모른다. 그래서 실제로 그것을 알아낼 수있는 유일한 방법은 가능한 어떤 방식 으로든 그것을 찌르고 그것에 대해 유용한 정보를 찾는 것입니다. 따라서 Scripting.Dictionary와 같은보다 친숙한 인터페이스를 사용하여 새 객체를 만드는 것이 더 쉬워지고 JScript 배열 객체의 데이터를 복사하여 JScript의 기본 배열 대신 C #에 전달합니다.
test.js :
var x = new ActiveXObject("Dmitry.YetAnotherTestObject.YetAnotherTestObject");
x.send([1, 2, 3, 4]);
YetAnotherTestObject.cs
using System;
using System.Runtime.InteropServices;
namespace Dmitry.YetAnotherTestObject
{
[Guid("C612BD9B-74E0-4176-AAB8-C53EB24C2B29"), ComVisible(true)]
public class YetAnotherTestObject
{
public void send(object x)
{
System.Console.WriteLine(x.GetType().Name);
}
}
}
위의 "__ComObject"는 C #의 관점에서 볼 때 다소 블랙 박스입니다.
또 다른 흥미로운 개념은 코드 작성 방법과 명령 실행 방법을 알고있는 컴퓨터에 대한 이해가있을 수 있으므로 프로그래머는 컴퓨터가 두뇌에서 프로그램으로 수행하려는 작업의 개념을 효과적으로 마샬링하는 것입니다 영상. 마샬 러가 충분하다면, 우리가하고 싶은 일 / 변경을 생각할 수있을뿐 아니라 키보드를 입력하지 않아도 프로그램이 변경 될 것입니다. 따라서 실제로 세미콜론을 작성하려는 몇 초 동안 뇌의 모든 신체적 변화를 저장할 수있는 방법이 있다면 해당 데이터를 신호에 마샬링하여 세미콜론을 인쇄 할 수는 있지만 극단적입니다.
마샬링에 대한 나의 이해는 다른 답변과 다릅니다.
직렬화 :
규칙을 사용하여 와이어 형식 버전의 객체 그래프를 생성하거나 재수 화합니다.
마샬링 :
매핑 파일을 사용하여 와이어 형식 버전의 객체 그래프를 생성하거나 재수 화하여 결과를 사용자 지정할 수 있습니다. 도구는 규칙을 준수하여 시작할 수 있지만 중요한 차이점은 결과를 사용자 정의하는 기능입니다.
최초 계약 개발 :
마샬링은 계약 첫 개발의 맥락에서 중요합니다.
Hydrating an object is taking an object that exists in memory, that doesn't yet contain any domain data ("real" data), and then populating it with domain data (such as from a database, from the network, or from a file system).
바이트 스트림 -스트림은 데이터 시퀀스입니다. 입력 스트림-소스에서 데이터를 읽습니다. 출력 스트림-데이터를 desitnation에 기록합니다. Java 바이트 스트림은 바이트 단위로 입출력을 수행하는 데 사용됩니다 (한 번에 8 비트). 바이트 스트림은 이진 파일과 같은 원시 데이터를 처리하는 데 적합합니다. Java 문자 스트림은 한 번에 2 바이트 씩 입력 / 출력을 수행하는 데 사용됩니다. 문자는 각 문자마다 2 바이트로 Java에서 유니 코드 규칙을 사용하여 저장되기 때문입니다. 문자 스트림은 텍스트 파일을 처리 (읽기 / 쓰기) 할 때 유용합니다.
RMI (Remote Method Invocation)-Java로 분산 애플리케이션을 작성하는 메커니즘을 제공하는 API입니다. RMI는 객체가 다른 JVM에서 실행되는 객체에서 메소드를 호출 할 수 있도록합니다.
직렬화 와 마샬링 은 모두 동의어로 느슨하게 사용됩니다. 몇 가지 차이점이 있습니다.
직렬화 -객체의 데이터 멤버는 이진 형식 또는 바이트 스트림으로 작성된 다음 파일 / 메모리 / 데이터베이스 등으로 쓸 수 있습니다. 오브젝트 데이터 멤버가 2 진 형식으로 작성된 후에는 데이터 유형에 대한 정보를 보유 할 수 없습니다.
Marshalling -Object는 data-type + Codebase가 연결된 상태에서 직렬화 (2 진 형식의 바이트 스트림으로) 된 다음 Remote Object (RMI) 전달 됩니다. 마샬링은 데이터 유형을 사전 결정된 명명 규칙으로 변환하여 초기 데이터 유형과 관련하여 재구성 할 수 있습니다.
직렬화는 마샬링의 일부입니다.
CodeBase 는이 객체의 구현을 찾을 수있는 곳의 Object 수신자에게 알려주는 정보입니다. 이전에 보지 못한 다른 프로그램으로 객체를 전달할 수 있다고 생각하는 프로그램은 코드베이스를 설정해야 코드를 로컬에서 사용할 수없는 경우 수신자가 코드를 다운로드 할 위치를 알 수 있습니다. 수신자는 객체를 직렬화 해제 할 때 객체에서 코드베이스를 가져와 해당 위치에서 코드를로드합니다. (@Nasir 답변에서 복사)
직렬화 는 객체가 사용하는 메모리의 바보 같은 메모리 덤프와 거의 비슷하지만 Marshalling 은 사용자 정의 데이터 유형에 대한 정보를 저장합니다.
어떤 방식으로, 직렬화는 데이터 유형의 정보가 전달되지 않고 기본 형식 만 바이트 스트림으로 전달되므로 값별 전달을 구현하여 마샬링을 수행합니다.
다른 OS에 동일한 데이터를 나타내는 다른 수단이있는 경우 스트림이 한 OS에서 다른 OS로 이동하는 경우 직렬화에는 빅 엔디안, 소규모 엔디안과 관련된 일부 문제가있을 수 있습니다. 반면 마샬링은 결과가 상위 수준이기 때문에 OS간에 마이그레이션하는 것이 좋습니다.