[C#/COMMON] MemoryMappedFile 클래스 : CreateNew 정적 메소드를 사용해 시스템 메모리에서 메모리 매핑 파일 만들기
C#/Common 2022. 5. 25. 20:16728x90
반응형
728x170
[TestLibrary 프로젝트]
▶ SharedMemoryHelper.cs
using System.IO.MemoryMappedFiles;
namespace TestLibrary
{
/// <summary>
/// 공유 메모리 헬퍼
/// </summary>
public static class SharedMemoryHelper
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Public
#region 쓰기 - Write<T>(mapName, mapSize, offset, source)
/// <summary>
/// 쓰기
/// </summary>
/// <typeparam name="T">구조체 타입</typeparam>
/// <param name="mapName">맵 명칭</param>
/// <param name="mapSize">맵 크기</param>
/// <param name="offset">위치</param>
/// <param name="source">소스</param>
public static void Write<T>(string mapName, long mapSize, long offset, T source) where T : struct
{
MemoryMappedFile file = MemoryMappedFile.CreateNew(mapName, mapSize);
MemoryMappedViewAccessor accessor = file.CreateViewAccessor();
accessor.Write<T>(offset, ref source);
}
#endregion
#region 읽기 - Read<T>(mapName, offset)
/// <summary>
/// 읽기
/// </summary>
/// <typeparam name="T">구조체 타입</typeparam>
/// <param name="mapName">맵 명칭</param>
/// <param name="offset">오프셋</param>
/// <returns>구조체</returns>
public static T Read<T>(string mapName, long offset) where T : struct
{
using(MemoryMappedFile file = MemoryMappedFile.OpenExisting(mapName))
{
using(MemoryMappedViewStream stream = file.CreateViewStream(0, StructureHelper.SizeOf(typeof(T))))
{
using(MemoryMappedViewAccessor accessor = file.CreateViewAccessor())
{
T target;
accessor.Read(offset, out target);
return target;
}
}
}
}
#endregion
}
}
728x90
▶ StructureHelper.cs
using System;
using System.Collections.Generic;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
namespace TestLibrary
{
/// <summary>
/// 구조체 헬퍼
/// </summary>
public static class StructureHelper
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 타입 딕셔너리
/// </summary>
private static Dictionary<Type, int> _typeDictionary = new Dictionary<Type, int>();
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Public
#region 크기 구하기 - SizeOf(type)
/// <summary>
/// 크기 구하기
/// </summary>
/// <param name="type">타입</param>
/// <returns>크기</returns>
public static int SizeOf(Type type)
{
int size;
if(_typeDictionary.TryGetValue(type, out size))
{
return size;
}
size = GetSize(type);
_typeDictionary.Add(type, size);
return size;
}
#endregion
#region 복사하기 - Copy(source, target)
/// <summary>
/// 복사하기
/// </summary>
/// <param name="source">소스 문자열</param>
/// <param name="target">타겟 포인터</param>
public unsafe static void Copy(string source, char* target)
{
char[] sourceCharArray = source.ToCharArray();
Marshal.Copy(sourceCharArray, 0, new IntPtr(target), sourceCharArray.Length);
}
#endregion
#region 문자열 구하기 - GetString(sourcePointer)
/// <summary>
/// 문자열 구하기
/// </summary>
/// <param name="sourcePointer">소스 포인터</param>
/// <returns>문자열</returns>
public unsafe static string GetString(char* sourcePointer)
{
return new string(sourcePointer);
}
#endregion
//////////////////////////////////////////////////////////////////////////////// Private
#region 크기 - GetSize(type)
/// <summary>
/// 크기 구하기
/// </summary>
/// <param name="type">타입</param>
/// <returns>크기</returns>
private static int GetSize(Type type)
{
DynamicMethod dynamicMethod = new DynamicMethod("SizeOfType", typeof(int), new Type[] { });
ILGenerator ilGenerator = dynamicMethod.GetILGenerator();
ilGenerator.Emit(OpCodes.Sizeof, type);
ilGenerator.Emit(OpCodes.Ret);
return (int)dynamicMethod.Invoke(null, null);
}
#endregion
}
}
300x250
▶ Student.cs
using System;
namespace TestLibrary
{
/// <summary>
/// 학생
/// </summary>
public unsafe struct Student
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region Field
/// <summary>
/// ID
/// </summary>
public int ID;
/// <summary>
/// 성명
/// </summary>
public fixed char Name[20];
/// <summary>
/// 생성 시간
/// </summary>
public DateTime CreateTime;
#endregion
}
}
반응형
[TestServer 프로젝트]
▶ Program.cs
using System;
using TestLibrary;
namespace TestServer
{
/// <summary>
/// 프로그램
/// </summary>
class Program
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Private
#region 프로그램 시작하기 - Main()
/// <summary>
/// 프로그램 시작하기
/// </summary>
private unsafe static void Main()
{
Console.WriteLine("공유 메모리 쓰기를 실행합니다.");
Student student = new Student();
student.ID = 1;
student.CreateTime = DateTime.Now;
StructureHelper.Copy("홍길동", student.Name);
SharedMemoryHelper.Write("testMap", 1000, 0, student);
Console.WriteLine($"ID : {student.ID}");
Console.WriteLine($"성명 : {StructureHelper.GetString(student.Name)}");
Console.WriteLine($"생성 시간 : {student.CreateTime}");
Console.ReadKey(false);
}
#endregion
}
}
[TestClient 프로젝트]
▶ Program.cs
using System;
using System.Threading;
using TestLibrary;
namespace TestClient
{
/// <summary>
/// 프로그램
/// </summary>
class Program
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Private
#region 프로그램 시작하기 - Main()
/// <summary>
/// 프로그램 시작하기
/// </summary>
private unsafe static void Main()
{
Thread.Sleep(1000); // 테스트시 서버에서 공유 메모리를 쓰는 시간을 반영한다.
Console.WriteLine("공유 메모리 읽기를 실행합니다.");
Student student = SharedMemoryHelper.Read<Student>("testMap", 0);
Console.WriteLine($"ID : {student.ID}");
Console.WriteLine($"성명 : {StructureHelper.GetString(student.Name)}");
Console.WriteLine($"생성 시간 : {student.CreateTime}");
Console.ReadKey(false);
}
#endregion
}
}
728x90
반응형
그리드형(광고전용)
'C# > Common' 카테고리의 다른 글
[C#/COMMON/.NET6] Buffer 클래스 : BlockCopy 정적 메소드를 사용해 인코딩 배제 문자열 바이트 배열 구하기 (0) | 2022.06.20 |
---|---|
[C#/COMMON] MemoryMappedFile 클래스 : CreateFromFile 정적 메소드를 사용해 메모리 매핑 파일 만들기 (0) | 2022.05.25 |
[C#/COMMON] FileSystem 클래스 : CopyDirectory 정적 메소드를 사용해 디렉토리 복사하기 (0) | 2022.05.25 |
[C#/COMMON] Marshal 클래스 : Copy 정적 메소드를 사용해 문자열을 fixed char 필드에 복사하기 (0) | 2022.05.25 |
[C#/COMMON] DynamicMethod 클래스 : Invoke 메소드를 사용해 구조체 크기 구하기 (0) | 2022.05.25 |
[C#/COMMON/.NET5] 콘솔 폰트 설정하기 (0) | 2022.05.24 |
[C#/COMMON] WebClient 클라이언트 : 서버 인코딩 타입에 맞춰 문자열 다운로드하기 (0) | 2022.05.24 |
[C#/COMMON] 이스케이프 유니코드 문자열 구하기 (0) | 2022.05.23 |
[C#/COMMON] Process 클래스 : 원격 데스크톱 실행하기 (0) | 2022.05.13 |
[C#/COMMON] Process 클래스 : 원격 데스크톱 계정 등록하기 (0) | 2022.05.13 |
댓글을 달아 주세요