美文网首页
二、PC集成unity(3)共享内存方式通信

二、PC集成unity(3)共享内存方式通信

作者: GameObjectLgy | 来源:发表于2023-03-30 10:40 被阅读0次
unity端
using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;

namespace ShareMemLib
{
    public class ShareMemory
    {
        private Semaphore m_Write;  //可写的信号
        private Semaphore m_Read;  //可读的信号
        private IntPtr handle;     //文件句柄
        private IntPtr addr;       //共享内存地址
        //uint mapLength = 400000;            //共享内存长
        uint mapLength = 4940860;            //共享内存长

        //构造函参
        string _writeMap = "WriteMap";
        string _readMap = "ReadMap";
        string _shareMemory = "shareMemory";
        string _rwsMap = "ReadMapWriteMapshareMemory";
        public delegate void RecMethod(string recMsg);
        private RecMethod _recMethod;
        private bool _isListener = false;

        #region 构造函数
        private ShareMemory() { }

        public ShareMemory(string map, bool isListener, RecMethod RecMethod = null)
        {
            if (string.IsNullOrEmpty(map))
            {
                throw new ArgumentNullException("The map can not empty");
            }
            //mapLength = 1024;
            _writeMap = map + "write";
            _readMap = map + "read";
            _shareMemory = map + "memory";
            _rwsMap = _readMap + _writeMap + _shareMemory;
            _recMethod = RecMethod;

            if (isListener)
            {
                StartListening();
                _isListener = true;
            }
        }
        ~ShareMemory()
        {
            Dispose();
        }
        #endregion

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="msg"></param>
        public void Send(string msg)
        {
            //监听者不能发送消息,会导致监听者收到自身发送的消息
            if (_isListener)
            {
                return;
            }
            try
            {
                m_Write = Semaphore.OpenExisting(_writeMap);
                m_Read = Semaphore.OpenExisting(_readMap);
                handle = OpenFileMapping(FILE_MAP_WRITE, 0, _shareMemory);
                addr = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);

                Write(msg);//写入信息

                m_Write.WaitOne();
                m_Read.Release();

            }
            catch (Exception ex)
            {

            }
        }
        Thread listenTh;
        /// <summary>
        /// 启动监听
        /// </summary>
        private void StartListening()
        {
            m_Write = new Semaphore(1, 1, _writeMap);//开始的时候有一个可以写
            m_Read = new Semaphore(0, 1, _readMap);//没有数据可读
            //mapLength = 1024;
            IntPtr hFile = new IntPtr(INVALID_HANDLE_VALUE);
            handle = CreateFileMapping(hFile, 0, PAGE_READWRITE, 0, mapLength, _shareMemory);
            addr = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);

            //启动监听线程
            listenTh = new Thread(() =>
            {
                while (true)
                {
                    try
                    {
                        m_Read.WaitOne();
                        m_Write.Release();
                        string recMsg = Read();
                        //触发接收消息处理方法
                        if (_recMethod != null)
                        {
                            //读取并传递接收信息
                            _recMethod(recMsg);
                        }
                    }
                    catch (Exception ex)
                    {
                        continue;
                    }
                }
            });
            listenTh.Start();
        }
        /// <summary>
        /// 读取信息
        /// </summary>
        /// <param name="mapName"></param>
        /// <param name="encoding"></param>
        private string Read(Encoding encoding = null)
        {
            long capacity = 1 << 10 << 10;
            string output = "";
            //打开共享内存   
            using (var mmf = MemoryMappedFile.OpenExisting(_rwsMap))
            {
                //使用CreateViewStream方法返回stream实例   
                using (var mmViewStream = mmf.CreateViewStream(0, capacity))
                {
                    //这里要制定Unicode编码否则会出问题   
                    using (BinaryReader rdr = new BinaryReader(mmViewStream, encoding == null ? Encoding.Unicode : encoding))
                    {
                        mmViewStream.Seek(0, SeekOrigin.Begin);
                        int length = rdr.ReadInt32();
                        char[] chars = rdr.ReadChars(length);
                        output = new string(chars);
                    }
                }
            }
            return output;
        }

        MemoryMappedFile mmf;
        MemoryMappedViewAccessor viewAccessor;
        /// <summary>
        /// 写入信息
        /// </summary>
        /// <param name="input"></param>
        private void Write(string input)
        {
            long capacity = 1 << 10 << 10;

            //创建或者打开共享内存   
            mmf = MemoryMappedFile.CreateOrOpen(_rwsMap, capacity, MemoryMappedFileAccess.ReadWrite);
            //通过MemoryMappedFile的CreateViewAccssor方法获得共享内存的访问器   
            viewAccessor = mmf.CreateViewAccessor(0, capacity);
            //向共享内存开始位置写入字符串的长度   
            viewAccessor.Write(0, input.Length);
            //向共享内存4位置写入字符   
            viewAccessor.WriteArray<char>(4, input.ToArray(), 0, input.Length);
        }

        /// <summary>
        /// 释放内存
        /// </summary>
        public void Dispose()
        {
            if (viewAccessor != null)
            {
                viewAccessor.Dispose();
            }
            if (mmf != null)
            {
                mmf.Dispose();
            }
            if (listenTh != null)
            {
                listenTh.Abort();
            }
        }

        #region API
        const int INVALID_HANDLE_VALUE = -1;
        const int PAGE_READWRITE = 0x04;

        //共享内存
        [DllImport("Kernel32.dll", EntryPoint = "CreateFileMapping")]
        private static extern IntPtr CreateFileMapping(IntPtr hFile, //HANDLE hFile,
         UInt32 lpAttributes,//LPSECURITY_ATTRIBUTES lpAttributes,  //0
         UInt32 flProtect,//DWORD flProtect
         UInt32 dwMaximumSizeHigh,//DWORD dwMaximumSizeHigh,
         UInt32 dwMaximumSizeLow,//DWORD dwMaximumSizeLow,
         string lpName//LPCTSTR lpName
         );

        [DllImport("Kernel32.dll", EntryPoint = "OpenFileMapping")]
        private static extern IntPtr OpenFileMapping(
         UInt32 dwDesiredAccess,//DWORD dwDesiredAccess,
         int bInheritHandle,//BOOL bInheritHandle,
         string lpName//LPCTSTR lpName
         );

        const int FILE_MAP_ALL_ACCESS = 0x0002;
        const int FILE_MAP_WRITE = 0x0002;

        [DllImport("Kernel32.dll", EntryPoint = "MapViewOfFile")]
        private static extern IntPtr MapViewOfFile(
         IntPtr hFileMappingObject,//HANDLE hFileMappingObject,
         UInt32 dwDesiredAccess,//DWORD dwDesiredAccess
         UInt32 dwFileOffsetHight,//DWORD dwFileOffsetHigh,
         UInt32 dwFileOffsetLow,//DWORD dwFileOffsetLow,
         UInt32 dwNumberOfBytesToMap//SIZE_T dwNumberOfBytesToMap
         );
        [DllImport("Kernel32.dll", EntryPoint = "UnmapViewOfFile")]
        private static extern int UnmapViewOfFile(IntPtr lpBaseAddress);
        [DllImport("Kernel32.dll", EntryPoint = "CloseHandle")]
        private static extern int CloseHandle(IntPtr hObject);
        #endregion
    }
}

这里开辟了多个共享内存,实际情况看需要。

另一端
using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;

namespace ShareMemLib
{
    public class ShareMemory
    {
        private Semaphore m_Write;  //可写的信号
        private Semaphore m_Read;  //可读的信号
        private IntPtr handle;     //文件句柄
        private IntPtr addr;       //共享内存地址
        uint mapLength = 4940860;            //共享内存长

        //构造函参
        string _writeMap = "WriteMap";
        string _readMap = "ReadMap";
        string _shareMemory = "shareMemory";
        string _rwsMap = "ReadMapWriteMapshareMemory";
        public delegate void RecMethod(string recMsg);
        private RecMethod _recMethod;
        private bool _isListener = false;

        private int ptrTemp = -1;

        #region 构造函数
        private ShareMemory() { }

        public ShareMemory(string map, bool isListener, RecMethod RecMethod = null, int ptr = 0)
        {
            if (string.IsNullOrEmpty(map))
            {
                throw new ArgumentNullException("The map can not empty");
            }
            if (handle != null)
            {
                ptrTemp = ptr;
            }
            //mapLength = 1920 * 1080;
            _writeMap = map + "write";
            _readMap = map + "read";
            _shareMemory = map + "memory";
            _rwsMap = _readMap + _writeMap + _shareMemory;
            _recMethod = RecMethod;

            if (isListener)
            {
                StartListening();
                _isListener = true;
            }
        }
        ~ShareMemory()
        {
            Dispose();
        }
        #endregion

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="msg"></param>
        public void Send(string msg)
        {
            //监听者不能发送消息,会导致监听者收到自身发送的消息
            if (_isListener)
            {
                return;
            }
            try
            {
                m_Write = Semaphore.OpenExisting(_writeMap);
                m_Read = Semaphore.OpenExisting(_readMap);
                handle = OpenFileMapping(FILE_MAP_WRITE, 0, _shareMemory);
                addr = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);

                Write(msg);//写入信息

                m_Write.WaitOne();
                m_Read.Release();

            }
            catch (Exception ex)
            {

            }
        }
        Thread listenTh;
        /// <summary>
        /// 启动监听
        /// </summary>
        private void StartListening()
        {
            m_Write = new Semaphore(1, 1, _writeMap);//开始的时候有一个可以写
            m_Read = new Semaphore(0, 1, _readMap);//没有数据可读
            //mapLength = 1920 * 1080;
            //IntPtr hFile = new IntPtr(INVALID_HANDLE_VALUE);
            IntPtr hFile = new IntPtr(ptrTemp);
            handle = CreateFileMapping(hFile, 0, PAGE_READWRITE, 0, mapLength, _shareMemory);
            addr = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);

            //启动监听线程
            listenTh = new Thread(() =>
            {
                while (true)
                {
                    try
                    {
                        m_Read.WaitOne();
                        m_Write.Release();
                        string recMsg = Read();
                        //触发接收消息处理方法
                        if (_recMethod != null)
                        {
                            //读取并传递接收信息
                            _recMethod(recMsg);
                        }
                    }
                    catch (Exception ex)
                    {
                        continue;
                    }
                }
            });
            listenTh.Start();
        }
        /// <summary>
        /// 读取信息
        /// </summary>
        /// <param name="mapName"></param>
        /// <param name="encoding"></param>
        private string Read(Encoding encoding = null)
        {
            long capacity = 1 << 10 << 10;
            string output = "";
            //打开共享内存   
            using (var mmf = MemoryMappedFile.OpenExisting(_rwsMap))
            {
                //使用CreateViewStream方法返回stream实例   
                using (var mmViewStream = mmf.CreateViewStream(0, capacity))
                {
                    //这里要制定Unicode编码否则会出问题   
                    using (BinaryReader rdr = new BinaryReader(mmViewStream, encoding == null ? Encoding.Unicode : encoding))
                    {
                        mmViewStream.Seek(0, SeekOrigin.Begin);
                        int length = rdr.ReadInt32();
                        char[] chars = rdr.ReadChars(length);
                        output = new string(chars);
                    }
                }
            }
            return output;
        }

        MemoryMappedFile mmf;
        MemoryMappedViewAccessor viewAccessor;
        /// <summary>
        /// 写入信息
        /// </summary>
        /// <param name="input"></param>
        private void Write(string input)
        {
            long capacity = 1 << 10 << 10;

            //创建或者打开共享内存   
            mmf = MemoryMappedFile.CreateOrOpen(_rwsMap, capacity, MemoryMappedFileAccess.ReadWrite);
            //通过MemoryMappedFile的CreateViewAccssor方法获得共享内存的访问器   
            viewAccessor = mmf.CreateViewAccessor(0, capacity);
            //向共享内存开始位置写入字符串的长度   
            viewAccessor.Write(0, input.Length);
            //向共享内存4位置写入字符   
            viewAccessor.WriteArray<char>(4, input.ToArray(), 0, input.Length);
        }

        /// <summary>
        /// 释放内存
        /// </summary>
        public void Dispose()
        {
            if (viewAccessor != null)
            {
                viewAccessor.Dispose();
            }
            if (mmf != null)
            {
                mmf.Dispose();
            }
            if (listenTh != null)
            {
                listenTh.Abort();
            }
        }

        #region API
        const int INVALID_HANDLE_VALUE = -1;
        const int PAGE_READWRITE = 0x04;

        //共享内存
        [DllImport("Kernel32.dll", EntryPoint = "CreateFileMapping")]
        private static extern IntPtr CreateFileMapping(IntPtr hFile, //HANDLE hFile,
         UInt32 lpAttributes,//LPSECURITY_ATTRIBUTES lpAttributes,  //0
         UInt32 flProtect,//DWORD flProtect
         UInt32 dwMaximumSizeHigh,//DWORD dwMaximumSizeHigh,
         UInt32 dwMaximumSizeLow,//DWORD dwMaximumSizeLow,
         string lpName//LPCTSTR lpName
         );

        [DllImport("Kernel32.dll", EntryPoint = "OpenFileMapping")]
        private static extern IntPtr OpenFileMapping(
         UInt32 dwDesiredAccess,//DWORD dwDesiredAccess,
         int bInheritHandle,//BOOL bInheritHandle,
         string lpName//LPCTSTR lpName
         );

        const int FILE_MAP_ALL_ACCESS = 0x0002;
        const int FILE_MAP_WRITE = 0x0002;

        [DllImport("Kernel32.dll", EntryPoint = "MapViewOfFile")]
        private static extern IntPtr MapViewOfFile(
         IntPtr hFileMappingObject,//HANDLE hFileMappingObject,
         UInt32 dwDesiredAccess,//DWORD dwDesiredAccess
         UInt32 dwFileOffsetHight,//DWORD dwFileOffsetHigh,
         UInt32 dwFileOffsetLow,//DWORD dwFileOffsetLow,
         UInt32 dwNumberOfBytesToMap//SIZE_T dwNumberOfBytesToMap
         );
        [DllImport("Kernel32.dll", EntryPoint = "UnmapViewOfFile")]
        private static extern int UnmapViewOfFile(IntPtr lpBaseAddress);
        [DllImport("Kernel32.dll", EntryPoint = "CloseHandle")]
        private static extern int CloseHandle(IntPtr hObject);
        #endregion
    }
}

实际是一模一样的

相关文章

  • Go channel-1

    不要以共享内存的方式去通信,而是以通信的方式共享内存 sync 鼓励使用channel channel的声明 ch...

  • jvm内存模型

    线程通信:线程之间通过共享内存,消息传递的方式进行通信:共享内存通过读取内存中的公共状态来达到彼此间的通信 - 其...

  • Go 临界资源

    出现临界资源访问问题的代码 不要以共享内存的方式去通信,而是以通信的方式共享内存 sync 鼓励使用channel...

  • android中的进程通信和Binder机制

    进程间通信的方式 共享内存创建共享内存区int shmget(key_tkey,size_t size,int s...

  • 进程通信:共享内存,套接字

    进程通信方式:共享内存 共享内存本质上就是每个进程将虚拟地址空间指向共享内存块中,当一个进程往一个共享内存快中写入...

  • Go - Channel

    设计理念 执行业务处理的 goroutine 不要通过共享内存的方式通信,而是要通过 Channel 通信的方式分...

  • Unity3 d 内存管理

    Unity3 d 内存管理 Unity几种动态加载Prefab方式的差异:其实存在3种加载prefab的方式: 一...

  • JAVA进阶(4)—— 内存模型

    基础 并发编程需要处理的两个关键问题:线程通信和线程同步 线程通信 线程通信的两种方式:共享内存和消息传递 共享...

  • Go的Goroutine的使用

    并发 concurrency Goroutine 通过通信来共享内存,而不是通过共享内存来通信 Channel是G...

  • 4. 进程间通信--共享内存、信号灯

    共享内存 共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝. int shmg...

网友评论

      本文标题:二、PC集成unity(3)共享内存方式通信

      本文链接:https://www.haomeiwen.com/subject/hmdcldtx.html