Как слушатель может снова подключить клиента

#c# #sockets #tcpclient #tcplistener

#c# #сокеты #tcpclient #tcplistener

Вопрос:

Я использую следующий пример для получения XML-сообщений. Клиент подключается, отправляет сообщение, а затем закрывает соединение. Однако слушатель отвечает только на первое соединение. Если клиент повторно подключается после закрытия, ничего не происходит. Поэтому слушатель должен распознавать, когда клиент повторно подключается через тот же порт. Я пробовал совсем немного, но не получил желаемого результата.

Кто-нибудь видит решение для этого примера?

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Xml;
using System.Xml.Linq;

namespace Socket_Server_Form
{
    public partial class Socket_Server : Form
    {
        private Thread n_server;        
        private Thread n_send_server;
        private TcpClient client;
        private TcpListener listener;
        private int port = 708;
        private string IP = "";
        private Socket socket;
        byte[] bufferReceive = new byte[4096];
        byte[] bufferSend = new byte[4096];        

        public Socket_Server()
        {
            InitializeComponent();
        }
    
        public void Server()
        {
            listener = new TcpListener(IPAddress.Any, port);
            listener.Start();
            try
            {
                socket = listener.AcceptSocket();
                if (socket.Connected)
                {
                    txtMessages.Invoke((MethodInvoker)delegate { txtStatus.Text = "Client: "   socket.RemoteEndPoint.ToString(); });
                }
                while (true)
                {
                    int length = socket.Receive(bufferReceive);
                    if (length > 0)
                    {
                        txtMessages.Invoke((MethodInvoker)delegate { txtMessages.Text = Encoding.UTF8.GetString(bufferReceive); });
                    }
                }
            }
            catch (Exception ex)
            {
                txtMessages.Invoke((MethodInvoker)delegate { txtStatus.Text = ("Error : "   ex.Message); });
            } 
            finally
            {
                listener.Stop();
                n_server = new Thread(new ThreadStart(Server));
                n_server.IsBackground = true;
                n_server.Abort();

                txtMessages.Invoke((MethodInvoker)delegate { txtStatus.Text = ("Receiver stopped"); });

                if (socket != null)
                {                    
                    n_server = new Thread(new ThreadStart(Server));
                    n_server.IsBackground = true;
                    n_server.Start();

                    txtMessages.Invoke((MethodInvoker)delegate { txtStatus.Text = ("Receiver started, waitig for next connection..."); });
                }
            }
        }

        private void send()
        {
            if (socket != null)
            {
                bufferSend = Encoding.UTF8.GetBytes(TxtSend.Text);
                socket.Send(bufferSend);
            }
            else
            {
                if (client.Connected)
                {
                    bufferSend = Encoding.UTF8.GetBytes(txtMessages.Text);
                    NetworkStream nts = client.GetStream();
                    if (nts.CanWrite)
                    {
                        nts.Write(bufferSend, 0, bufferSend.Length);
                    }
                }
            }
        }

        private void BtnStart_Click(object sender, EventArgs e)
        {
            n_server = new Thread(new ThreadStart(Server));
            n_server.IsBackground = true;
            n_server.Start();
            txtStatus.Text = "Receiver started";
        }

        private void BtnStop_Click(object sender, EventArgs e)
        {
            n_server = new Thread(new ThreadStart(Server));
            n_server.IsBackground = true;
            n_server.Abort();
            txtStatus.Text = ("Receiver stopped");
        }        

        private void BtnSend_Click(object sender, EventArgs e)
        {
            n_send_server = new Thread(new ThreadStart(send));
            n_send_server.IsBackground = true;
            n_send_server.Start();
        }        
    }
}
 

Комментарии:

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

2. @ADyson сообщение в формате xml отправляется по TCP-сокету. Я не имею никакого влияния на структуру клиента. Сообщения получены и должны быть переведены из XML в CSV, а затем сохранены. Все уже работает. Единственная проблема заключается в том, что при повторном подключении клиента слушатель не реагирует. Как вы думаете, это можно было бы решить лучше с помощью HTTP-сервера?

3. Да, потому что HTTP-сервер (при условии, что вы просто используете готовый и не делаете ничего сумасшедшего, например, пытаетесь написать свой собственный) знает, когда начинается и заканчивается запрос, и продолжает прослушивать следующий запрос. Это просто работает. В .NET Core / 5 (и в более новых версиях .NET) в вашем приложении может быть запущен автономный HTTP-сервер. Но, конечно, если вы скажете, что не можете изменить клиента, который подключается к вашему серверу, тогда он не сможет работать — им также придется обновить, чтобы записать его как HTTP-клиент вместо необработанного TCP-клиента.

4. Клиентские компьютеры являются депозитными. к сожалению, я не имею на это никакого влияния. Так что это должно быть решение для сокетов. На самом деле, не так много не хватает, слушатель просто не замечает, когда клиент отключается.

5. В этом примере есть ли какой-либо способ узнать, когда клиент отключил соединение?