Ожидание входящего запроса tcp / ip сервера - PullRequest
0 голосов
/ 23 мая 2018

Я создаю соединение TCP / IP для своего приложения с системой хранилища.Связь происходит следующим образом.

  • Я отправляю сообщение на сервер TCP / IP (Socket) системы хранилища.
  • Система хранилища отвечает сообщением «Мой локальный TCP»./ IP-сервер.

Таким образом, нет прямых ответных сообщений.Вместо этого каждое приложение как собственный сервер.Тем не менее, я хочу, чтобы мое приложение ожидало ответа от другого сервера.

Итак, в основном у меня есть следующий код.

public string ControllerFunction() {
    startLocalTcpIpServer();
    sendMessage("a message");

    return clientMessage;
}

Это мой собственный сервер, запущенный с помощью start ()function

    public void Start() {
        // Start TcpServer background thread        
        tcpListenerThread = new Thread(new ThreadStart(ListenForIncommingRequests)) {
            IsBackground = true
        };
        tcpListenerThread.Start();
    }

    private void ListenForIncommingRequests() {
        try {
            tcpListener = new TcpListener(IPAddress.Parse(serverIp), port);
            tcpListener.Start();
            byte[] bytes = new byte[1024];
            Console.WriteLine("Server Started");
            while(true) {
                // Get a stream object for reading 
                using(NetworkStream stream = tcpListener.AcceptTcpClient().GetStream()) {
                    int length;
                    // Read incomming stream into byte arrary.                      
                    while((length = stream.Read(bytes, 0, bytes.Length)) != 0) {
                        byte[] incommingData = new byte[length];
                        Array.Copy(bytes, 0, incommingData, 0, length);
                        // Convert byte array to string message.                            
                        string clientMessage = Encoding.ASCII.GetString(incommingData);
                    }
                }
            }
        }
        catch(SocketException socketException) {
            Console.WriteLine("SocketException " + socketException.ToString());
        }
    }

Поэтому я хочу снова использовать строку результата clientMessage в качестве возврата для моей ControllerFunction.Но как мне получить данные там надлежащим образом?

1 Ответ

0 голосов
/ 23 мая 2018

Итак, вам нужно дождаться ответа от другого места в вашем приложении (локальный сервер).Ответ будет запущен там первым.Локальный сервер должен иметь событие, на которое вы можете подписаться (OnMessage в моем примере).Это событие перешлет вам сообщение о результате.

Синхронизация может быть обработана с помощью TaskCompletionSource.Вы создадите задание, которое вы можете использовать для получения результата синхронно или асинхронно.

Примерно так:

public string ControllerFunction()
{           
    return ControllerFunctionTask().Result;
}

public Task<string> ControllerFunctionTask()
{            
    sendMessage("a message");

    var task = new TaskCompletionSource<string>();
    localServer.OnMessage = (message) =>
    {
        task.SetResult(message);
    };

    return task.Task;
}

Как указано в комментариях, синхронное ожидание асинхронного задания может привести к взаимоблокировке.Это может произойти, если поток вызывающей стороны - context thread (UI, ASP).Поэтому к этому лучше подходить:

public async Task<string> ControllerFunction()
{           
    return await ControllerFunctionTask();
}

public Task<string> ControllerFunctionTask()
{            
    sendMessage("a message");

    var task = new TaskCompletionSource<string>();
    localServer.OnMessage = (message) =>
    {
        task.SetResult(message);
    };

    return task.Task;
}

OnMessage можно определить следующим образом:

public event Action<string> OnMessage;

Тогда он будет вызван сразу после строки, где вы получите строку clientMessage:

string clientMessage = Encoding.ASCII.GetString(incommingData);
if (OnMessage != null)
     OnMessage(clientMessage);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...