CesatAGS Ответов: 1

Как я могу отправить массив pipe server C++ клиенту C#


у меня есть этот код PIPE Server C++
<pre>#include <stdio.h>
#include <stdint.h>
#include <winsock.h>
#include <string>

// see https://msdn.microsoft.com/en-us/library/bb546085(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1
// for information on creating pipe clients and servers in c++

using namespace std;

#pragma pack(1)
typedef struct {
	int8_t command;
	int32_t sockid;
	int32_t datasize;
} PipeHeader;
#pragma pack()

int wmain(int argc, wchar_t* argv[]) {

	int arrayNumber[70];
	auto pipename = "\\\\.\\pipe\\pipey"; // can be any name, but must start '\\.\pipe\'
	printf("Create pipe '%s'\r\n", pipename);
	auto pipeHandle = CreateNamedPipe(pipename,
		PIPE_ACCESS_DUPLEX,
		PIPE_TYPE_MESSAGE | PIPE_WAIT,
		1,  // # instances
		64, // out buff
		64, // in buff
		0,  // timeout, 0 = default of 50ms
		NULL); // security attrs
	printf("Waiting for pipe connect\r\n");
	if (ConnectNamedPipe(pipeHandle, NULL)) {
		printf("Pipe connected\r\n");
		PipeHeader hdr;
		DWORD bytesRead;
		int8_t cmd = -1;
		while (cmd != 0) {
			if (ReadFile(pipeHandle, &hdr, sizeof(PipeHeader), &bytesRead, NULL)) {
				// you can check or assert here that bytesRead == sizeof(PipeHeader)
				printf("Read %d bytes from pipe, {command: %d, sockid: %d, datasize: %d}\r\n",
					bytesRead, hdr.command, hdr.sockid, hdr.datasize);
				if (hdr.command == 0) { // assume 0 is the exit cmd
					break;
				}
				else if (hdr.command == 1) {
					
					while (true)
					{
						for (size_t i = 0; i < 70; i++)
						{
							 return arrayNumber[i] = i;
							 Sleep(100);
						}
						Sleep(100);
					}
				}
				hdr.command = 4;
				hdr.sockid = 101;
				hdr.datasize *= 2;
				if (WriteFile(pipeHandle, &hdr, sizeof(PipeHeader), &bytesRead, NULL)) {
					printf("Data written to pipe\r\n");
				}
				else {
					printf("Pipe write failed\r\n");
					break;
				}
			}
			else {
				printf("Read error: %d\r\n", GetLastError());
				break; // exit
			}
		}
		if (DisconnectNamedPipe(pipeHandle) == FALSE) {
			printf("Disconnect error: %d\r\n", GetLastError());
		}
	}
	else {
		printf("Pipe connect failed\r\n");
	}
	CloseHandle(pipeHandle);
	printf("Exiting program\r\n");
	return 0;
}


и мой клиент C#, который я хочу получить массив




<pre>using System;
using System.Runtime.InteropServices;
using System.IO.Pipes;

namespace PIPI_Client
{
    // see https://msdn.microsoft.com/en-us/library/bb546085(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1
    // for information on creating pipe clients and servers in c#
    class Program
    {
        [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
        public struct PipeHeader
        {
            [MarshalAs(UnmanagedType.I1)]
            public byte command;
            [MarshalAs(UnmanagedType.I4)]
            public Int32 sockid;
            public Int32 datasize;
        }

        static void Main(string[] args)
        {
            var pipename = "pipey";
            var pipeClient = new NamedPipeClientStream(pipename);
            Console.WriteLine("Connecting to server pipe '{0}'", pipename);
            pipeClient.Connect();
            var hdr = new PipeHeader();
            var hdrSize = Marshal.SizeOf(hdr);
            hdr.command = 1;
            hdr.sockid = 1912;
            hdr.datasize = 32;
            var buf = Serialize(hdr);
            Console.WriteLine("Writing to server pipe");
            pipeClient.Write(buf, 0, hdrSize);
            pipeClient.Read(buf, 0, hdrSize);
            hdr = (PipeHeader)Deserialize(buf, hdr.GetType());
            Console.WriteLine("Pipe read {{ command: {0}, sockid: {1}, datasize: {2} }}",
                               hdr.command, hdr.sockid, hdr.datasize);

            //receive array from client some where?

            hdr.command = 1; // tell server to disconnect
            buf = Serialize(hdr);
            Console.WriteLine("Sending disconnect");
            pipeClient.Write(buf, 0, hdrSize);
            pipeClient.Close();
            Console.WriteLine("Pipe closed");

            Console.ReadKey();
        }

        public static object Deserialize(byte[] rawdatas, Type anytype)
        {
            int rawsize = Marshal.SizeOf(anytype);
            if (rawsize > rawdatas.Length)
                return null;
            GCHandle handle = GCHandle.Alloc(rawdatas, GCHandleType.Pinned);
            IntPtr buffer = handle.AddrOfPinnedObject();
            object retobj = Marshal.PtrToStructure(buffer, anytype);
            handle.Free();
            return retobj;
        }

        public static byte[] Serialize(object obj)
        {
            int rawsize = Marshal.SizeOf(obj);
            var rv = new byte[rawsize];
            IntPtr ptr = Marshal.AllocHGlobal(rawsize);
            Marshal.StructureToPtr(obj, ptr, true);
            Marshal.Copy(ptr, rv, 0, rawsize);
            Marshal.FreeHGlobal(ptr);
            return rv;
        }
    }
}


соединение между сервером и клиентом работает нормально, но я не знаю, как передать массив клиенту
=/

Что я уже пробовал:

<pre lang="c#"><pre>using System;
using System.Runtime.InteropServices;
using System.IO.Pipes;

namespace PIPI_Client
{
    // see https://msdn.microsoft.com/en-us/library/bb546085(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1
    // for information on creating pipe clients and servers in c#
    class Program
    {
        [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
        public struct PipeHeader
        {
            [MarshalAs(UnmanagedType.I1)]
            public byte command;
            [MarshalAs(UnmanagedType.I4)]
            public Int32 sockid;
            public Int32 datasize;
        }

        static void Main(string[] args)
        {
            var pipename = "pipey";
            var pipeClient = new NamedPipeClientStream(pipename);
            Console.WriteLine("Connecting to server pipe '{0}'", pipename);
            pipeClient.Connect();
            var hdr = new PipeHeader();
            var hdrSize = Marshal.SizeOf(hdr);
            hdr.command = 1;
            hdr.sockid = 1912;
            hdr.datasize = 32;
            var buf = Serialize(hdr);
            Console.WriteLine("Writing to server pipe");
            pipeClient.Write(buf, 0, hdrSize);
            pipeClient.Read(buf, 0, hdrSize);
            hdr = (PipeHeader)Deserialize(buf, hdr.GetType());
            Console.WriteLine("Pipe read {{ command: {0}, sockid: {1}, datasize: {2} }}",
                               hdr.command, hdr.sockid, hdr.datasize);

            //receive array from client some where?

            hdr.command = 1; // tell server to disconnect
            buf = Serialize(hdr);
            Console.WriteLine("Sending disconnect");
            pipeClient.Write(buf, 0, hdrSize);
            pipeClient.Close();
            Console.WriteLine("Pipe closed");

            Console.ReadKey();
        }

        public static object Deserialize(byte[] rawdatas, Type anytype)
        {
            int rawsize = Marshal.SizeOf(anytype);
            if (rawsize > rawdatas.Length)
                return null;
            GCHandle handle = GCHandle.Alloc(rawdatas, GCHandleType.Pinned);
            IntPtr buffer = handle.AddrOfPinnedObject();
            object retobj = Marshal.PtrToStructure(buffer, anytype);
            handle.Free();
            return retobj;
        }

        public static byte[] Serialize(object obj)
        {
            int rawsize = Marshal.SizeOf(obj);
            var rv = new byte[rawsize];
            IntPtr ptr = Marshal.AllocHGlobal(rawsize);
            Marshal.StructureToPtr(obj, ptr, true);
            Marshal.Copy(ptr, rv, 0, rawsize);
            Marshal.FreeHGlobal(ptr);
            return rv;
        }
    }
}

tanchusegialai

у вас есть решение для вашей проблемы. Не могли бы вы пожалуйста разместить его? Я хочу того же решения.

1 Ответов

Рейтинг:
0

Rick York

Моя обычная тактика в подобных ситуациях заключается в том, чтобы клиент спрашивал сервер, а сервер отвечал тем, что его просят. Если вы не можете явно заставить клиента сделать это, то вы можете пересмотреть программы, чтобы клиент спросил сервер: "у вас есть что-нибудь для меня?", и сервер ответил тем, что вы сказали ему отправить клиенту. Я делал это несколько раз в прошлом над необработанными соединениями гнезд и труб, и это работает довольно хорошо.


CesatAGS

у вас есть демо-версия?