Как передать SOCKET (РУЧКА) из неуправляемой программы на C в дочерний процесс .NET? - PullRequest
0 голосов
/ 29 октября 2018

у нас есть служба Windows (WS), написанная на C. WS прослушивает порт для входящих запросов. Один из запросов - запустить дочерний процесс и передать ему SOCKET, чтобы запрашивающий сервер приложений (RAS) продолжал общаться с дочерним процессом впоследствии. Исполняемый файл дочернего процесса (CPE) также написан на языке Си.

Это (упрощенный) код WS:

... 
HANDLE curr_channel // is the SOCKET our WS got from accepting an incoming connection attempt
HANDLE process_h = GetCurrentProcess();
HANDLE new_channel;
DuplicateHandle(process_h, curr_channel, process_h, &new_channel, 0, TRUE, DUPLICATE_SAME_ACCESS); // note that bInheritHandles is set to TRUE (1)
char command_line[2048];
sprintf(command_line, "<path to executable to be started as child process> %Iu", (unsigned __int64)new_channel);
PROCESS_INFORMATION process_info;
memset(&process_info, 0, sizeof(PROCESS_INFORMATION));
STARTUPINFO startup;
memset(&startup, 0, sizeof(STARTUPINFO));
startup.cb = sizeof(STARTUPINFO);
CreateProcess(NULL, command_line, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &process_info); // note that bInheritHandles is set to TRUE (1)
CloseHandle(process_info.hThread);
CloseHandle(process_info.hProcess);
CloseHandle(new_channel);
...

Это (упрощенный) код CPE:

...
int pipeFd = atoi(argv[1]);
char *outBuf = ... // the message to be sent to the RAS as this is waiting for a (synchronous) response
int size = ... // length of this message
int cnt = send(pipeFd, outBuf, size, 0);
...

Это все работает как очарование в течение многих лет. Теперь мы хотели бы заменить CPE программой, написанной на C #, назовем ее CPE.NET. WS должен оставаться как есть (написано в C).

Это (упрощенный) код CPE.NET:

.
class Program {

    [DllImport("ws2_32.dll")]
    extern static int send([In] IntPtr socketHandle, [In] IntPtr buffer, [In] int count, [In] SocketFlags socketFlags);

    public static int Send(IntPtr socketHandle, byte[] buffer, int offset, int size, SocketFlags socketFlags) {
        unsafe {
            fixed (byte* pData = buffer) {
                return send(socketHandle, new IntPtr(pData + offset), size, socketFlags);
            }
        }
    }

    static void Main(string[] args) {
        int socketHandle;
        if (!int.TryParse(args[1], out socketHandle))
            return;
        byte[] data = new byte[] { ... }; // the message to be sent to the RAS as this is waiting for a (synchronous) response
        int retSendWithDotNet = Send(new IntPtr(socketHandle), data, 0, data.Length, 0);
        ...

Проблема теперь в том, что retSendWithDotNet всегда равен -1. Есть идеи, почему это так?

Спасибо, Michael

1 Ответ

0 голосов
/ 30 октября 2018

"Вам нужно вызвать WSAGetLastError, чтобы получить больше информации. Я предполагаю, что сокеты не инициализируются (см. WSAStartup)."

Простой, но эффективный. Вызов WSAStartup () сделал свое дело. Большое спасибо.

...