C # многопользовательское приложение Tcp / Ip Chat - PullRequest
0 голосов
/ 13 января 2019

Я планирую написать приложение на C #, которое может работать как сервер или как клиент. Я реализовал два WinForm. Первый из них называется ServerChat, который при загрузке вызывает backgroundWorker

private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
    serverSocket.Start();
    try
    {
        clientSocket = serverSocket.AcceptTcpClient();
        backgroundWorker1.ReportProgress(0, clientSocket);
    }
    catch (Exception exp)
    {
        throw exp;
    }
}

private void backgroundWorker1_ProgressChanged(object sender,
    System.ComponentModel.ProgressChangedEventArgs e)
{
    if (e.UserState!=null)
    {
        try
        {
            frmChatClient = new frmChatClient("server", clientSocket);
            frmChatClient.Show();
        }
        catch (Exception exp)
        {
            throw exp;
        }
    }
}

Как вы можете видеть, когда соединение принято, frmChatClient показал, что имеет свой собственный backgroundWorker для сокета чтения, который был передан в предыдущем.

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    byte[] bytesFrom = new byte[10025];

    while (true)
    {
        try
        {
           // in this line clientSocket is connected
            this.networkStream = clientSocket.GetStream();

           // this line throw exeotion
           networkStream.Read(bytesFrom, 0, textbox1.MaxLength);

            dataFromClient = System.Text.Encoding.BigEndianUnicode.GetString(bytesFrom);

            backgroundWorker1.ReportProgress(0,dataFromClient);
           // break;
        }
        catch (Exception ex)
        {
            throw ex;

        }
    }
}

После попытки чтения или записи я получил следующее сообщение об ошибке

Невозможно прочитать данные из транспортного соединения: существующее соединение было принудительно закрыто удаленным хостом.

1 Ответ

0 голосов
/ 13 января 2019

Соединение было закрыто из-за отсутствия трафика. Если это так, сокет закроет соединение.

TcpClient предназначен для использования при отправке / получении, а затем при закрытии. У него нет гибкости по сравнению с нижележащим сокетом. Вместо AcceptTcpClient вы можете использовать AcceptSocket для получения принятого соединения, а затем использовать TCP keep alive, чтобы поддерживать соединение в рабочем состоянии. Или, если вы хотите использовать TcpClient, обязательно отправляйте пакеты с поддержкой активности.

В вашем протоколе вы можете предоставить пакет ALIVE с небольшой полезной нагрузкой, просто чтобы сообщить серверу и клиенту, что соединение все еще установлено и ясно. Отправка этих типов пакетов вместо стандартного TCP Keep Alive имеет свои плюсы и минусы. Но обязательно заставит вашего клиента оставаться на связи.

...