Как отправить данные и получить ответ от Unix Socket с ядром .net - PullRequest
1 голос
/ 13 апреля 2019

Я пытаюсь связаться с Docker Daemon, используя ядро ​​dotnet.Я использовал это руководство, которое работает, как ожидалось.

Проблема, с которой я сталкиваюсь, заключается в том, что когда я пытаюсь отправить данные POST в конечную точку, чтобы изменить сервис докера (в основном я хотел бы иметь возможность масштабировать сервисы увеличения / уменьшения в этом случае), я 'используя тот же метод для отправки данных в сокет, но изменив содержимое:

Это метод GET для получения запущенных служб, который работает:

    public string GetAllServices()
    {
        var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
        var unixEndpoint = new UnixEndPoint("/var/run/docker.sock"); // this address is where the socket exists
        socket.Connect(unixEndpoint); // connect to the socket

        // create a request like this in HTTP spec format
        var request = $"GET /v1.24/services "
                        + "HTTP/1.1\r\n"
                        + "Host: unix\r\n"
                        + "Content-Length: 0\r\n"
                        + "accept-encoding: gzip\r\n"
                        + "Connection: keep-alive\r\n"
                        + "Accept: */*\r\n"
                        + "\r\n";

        // convert the request into byte data
        byte[] requestBytes = Encoding.ASCII.GetBytes(request);
        // send the request to the socket
        socket.Send(requestBytes);

        // get the header
        while (true)
        {
            var headerLine = ReceiveUntilCRLF(socket);
            if (headerLine == "\r\n")
            {
                break;
            }
            if (headerLine == "HTTP/1.1 400 Bad Request\r\n")
            {
                break;
            }
        }

        // get the payload
        var payload = "";
        byte[] chunkLengthBytes = new byte[512];
        var chunkLength = 0;
        while (true)
        {
            // get the length of the next chunk
            var temp = ReceiveUntilCRLF(socket);

            // get the chunk
            byte[] chunkBytes = new byte[chunkLength];
            payload += ReceiveUntilCRLF(socket);

            // append chunk to payload string
            if (payload.EndsWith("\r\n"))
            {
                break;
            }
        }
        // in the end, disconnect and close the socket to cleanup
        socket.Disconnect(false);
        socket.Close();

        return payload;
    }

Затем для обновления службы:

public void UpdateService(Services currentServiceState)
    {
        bool badRequest = false;
        var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
        var unixEndpoint = new UnixEndPoint("/var/run/docker.sock"); // this address is where the socket exists
        socket.Connect(unixEndpoint); // connect to the socket

        var body = JsonConvert.SerializeObject(currentServiceState, Formatting.Indented);


        string request = CreateRequestString($"/v1.24/services/{currentServiceState.Spec.Name}/update?version={currentServiceState.Version.Index}", body);

        // convert the request into byte data
        byte[] requestBytes = Encoding.ASCII.GetBytes(request);
        // send the request to the socket

        socket.Send(requestBytes);

        // get the header
        while (true)
        {
            var headerLine = ReceiveUntilCRLF(socket);
            if (headerLine == "\r\n")
            {
                break;
            }
            if (headerLine == "HTTP/1.1 400 Bad Request\r\n")
            {
                badRequest = true;
                string errorResponse = headerLine;
                while (true)
                {
                    var newLine = ReceiveUntilCRLF(socket);
                    errorResponse += newLine;

                    if (newLine == "\r\n")
                    {
                        Console.WriteLine($"{errorResponse}");
                        break;
                    }
                }
                break;
            }
        }

        if(!badRequest)
        {
            // get the payload
            var payload = "";
            byte[] chunkLengthBytes = new byte[512];
            var chunkLength = 0;
            while (true)
            {
                // get the length of the next chunk
                var temp = ReceiveUntilCRLF(socket);

                // get the chunk
                byte[] chunkBytes = new byte[chunkLength];
                payload += ReceiveUntilCRLF(socket);

                // append chunk to payload string
                Console.Write(payload);
                if (payload.EndsWith("\r\n"))
                {
                    break;
                }
            }

        }
        // in the end, disconnect and close the socket to cleanup
        socket.Disconnect(false);
        socket.Close();

    }

и CreateRequestString () выглядит следующим образом:

public string CreateRequestString(string endpoint, string content)
    {

        int contentLength = 0;
        if (content.Length > 0)
        {
            contentLength = Encoding.UTF8.GetBytes(content).Length;
        }

        var requestString = $"POST {endpoint} "
                        + "HTTP/1.1\r\n"
                        + "Host: unix\r\n"
                        + "accept-encoding: gzip\r\n"
                        + "Connection: keep-alive\r\n"
                        + $"content-length: {contentLength}\r\n"
                        + "Accept: */*\r\n"
                        + "\r\n";

        if (content.Length > 0)
        {
            requestString += $"{JsonConvert.DeserializeObject(content)}";
        }

        return requestString;
    }

, который возвращает неверный запрос 400.

Мне интересно, если либо: 1. AmЯ правильно рассчитал длину контента?2. Я правильно строю строку запроса?3. Есть что-то еще, что я пропустил?

Спасибо

...