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

2023-03-30  本文已影响0人  GameObjectLgy
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
    }
}

实际是一模一样的

上一篇 下一篇

猜你喜欢

热点阅读