Необходимо отправить FIN/ACK

Мне нужен приведенный ниже код для отправки FIN/ACK после завершения связи с сервером. Я использовал сокеты раньше, и вы прямо указываете ему закрыть соединение, после чего сетевая карта отправляет FIN/ACK. Здесь у меня нет такого контроля, и мне любопытно, есть ли способ заставить FIN / ACK. Когда я завершаю программу, отправляется FIN/ACK.

Я попытался разобрать объект, который поддерживает TCP-соединение открытым, но не уверен, что он работает правильно. Я попытался поместить его в свой собственный поток и установить для него значение void.

Чтобы запустить этот код в Visual Studio, вам нужно добавить ссылку на сервер (https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl) и назовите его Onvif_Video_Player.

using System;
using System.Text;
using System.Windows.Forms;
using Onvif_Video_Player.OnvifDevice;
using System.ServiceModel.Channels;
using System.ServiceModel;


namespace Onvif_Video_Player
{
    public partial class Form1 : Form
    {
        //Form1 Interactive Objecst 
        string IPAddress;
        String userName;
        string password;

        public Form1()
        {
            InitializeComponent();
        }

        private void GetProfiles_Click(object sender, EventArgs e)
        {
            IPAddress = txtbox_IPAddress.Text;
            userName = TxtBox_UserName.Text;
            password = TxtBox_Password.Text;
            GetOnvifProfiles();
            while (true)
            {
             //Do other stuff 
            }
        }

        private void GetOnvifProfiles()
        {
                UriBuilder deviceUri;
                System.ServiceModel.Channels.CustomBinding binding;

                deviceUri = new UriBuilder("Http:/onvif/device_service");

                HttpTransportBindingElement httpTransport = new HttpTransportBindingElement();
                httpTransport.AuthenticationScheme = System.Net.AuthenticationSchemes.Digest;
                deviceUri.Host = IPAddress;
                var messageElement = new TextMessageEncodingBindingElement();
                messageElement.MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None);
                System.ServiceModel.Channels.CustomBinding customBinding = new System.ServiceModel.Channels.CustomBinding(messageElement, httpTransport);
                binding = new System.ServiceModel.Channels.CustomBinding(new TextMessageEncodingBindingElement(MessageVersion.Soap12, Encoding.UTF8), httpTransport);
                DeviceClient Onvif_Device = new DeviceClient(binding, new EndpointAddress(deviceUri.ToString()));
                OnvifDevice.Service[] service = Onvif_Device.GetServices(false);
                ///////////////////////////Send FIN/ACK//////////////////////////
            }
        }
    }

Еще одна мысль: если бы я мог выяснить, на каком порту было открыто это TCP-соединение, я мог бы вручную создать строку для отправки FIN/ACK на этот порт.

Как рекомендуется ниже, я попытался использовать. Возможно, я делаю это неправильно: сначала я переместил свою функцию, которая создает TCP-соединение, в общедоступный класс, и этот класс наследовался от IDisposable.

Функция класса....

namespace Onvif_Video_Player
    {
        public class CustomBindingsAndClients : IDisposable
        {
            void IDisposable.Dispose() 
            {
                int i = 0;
            }
    
            public void GetProfiles(string IP, string IuserName, string password)
            {
                UriBuilder deviceUri = new UriBuilder("Http:/onvif/device_service");
                System.ServiceModel.Channels.CustomBinding binding;
                HttpTransportBindingElement httpTransport = new HttpTransportBindingElement();
                httpTransport.AuthenticationScheme = System.Net.AuthenticationSchemes.Digest;
                deviceUri.Host = "192.168.1.65";
                var messageElement = new TextMessageEncodingBindingElement();
                messageElement.MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None);
                System.ServiceModel.Channels.CustomBinding customBinding = new System.ServiceModel.Channels.CustomBinding(messageElement, httpTransport);
                binding = new System.ServiceModel.Channels.CustomBinding(new TextMessageEncodingBindingElement(MessageVersion.Soap12, Encoding.UTF8), httpTransport);
                DeviceClient Onvif_Device = new DeviceClient(binding, new EndpointAddress(deviceUri.ToString()));
                OnvifDevice.Service[] service = Onvif_Device.GetServices(true);
                binding = null;
            }
        }
    }

Затем в основной части кода экземпляр был заключен в оператор using...

        private void GetProfiles_Click(object sender, EventArgs e)
    {
        IPAddress = txtbox_IPAddress.Text;
        userName = TxtBox_UserName.Text;
        password = TxtBox_Password.Text;
        using (CustomBindingsAndClients TEMP = new CustomBindingsAndClients()) 
        {
            TEMP.GetProfiles(IPAddress, userName, password);
        }
     }

Тем не менее соединение TCP оставалось открытым, пока приложение не было закрыто.


person NewCode    schedule 22.01.2021    source источник
comment
Спасибо! Я не знал, что это вещь. Я попробовал это, и он кричит мне CS1674: Service[]: Type, используемый в операторе использования, должен быть неявно преобразован в «System.IDisposable». Я должен отметить: рукопожатие TCP происходит @, когда вызывается Onvif_Device.GetServices(false). Я попытался обернуть объект Onvif_Device в использование, и хотя это скомпилировалось и запустилось, это не решило мою проблему.   -  person NewCode    schedule 24.01.2021
comment
Вы просто говорите о изящном закрытии. Предоставленный вами код не дает ясности: а) почему вы считаете, что вам нужно работать на уровне IP FIN/ACK, б) какой уровень API вы собираетесь использовать для этого и в) какой конкретный< /i> у вас есть проблема, неважно, это что-то вроде минимально воспроизводимого примера, который потребуется для такого вопрос. Но см. дубликат для информации. Как правило, на уровне сокета вы хотите вызывать Shutdown(), на более высоких уровнях API вам может потребоваться просто удалить объект или использовать какой-либо механизм, который должен отключить соединение.   -  person Peter Duniho    schedule 24.01.2021
comment
а) Из-за конструктивных ограничений я могу одновременно открывать только одно TCP-соединение. б) это минимальный объем воспроизводимого кода. Вы можете скопировать и вставить это в новый проект, добавить ссылки, как было предложено, и код будет выполнен (при условии, что вы жестко кодируете такие вещи, как IP-адрес). c) Другая ссылка не отвечает на мой вопрос. Я уже просматривал этот ответ раньше. И эта ссылка не предлагает никакого способа избавления от объекта. Вот против чего я выступаю.   -  person NewCode    schedule 24.01.2021
comment
Количество соединений, которые вы можете открыть одновременно, не имеет ничего общего с тем, как изящно закрыть любое данное соединение. Я понятия не имею, почему ты вообще это поднимаешь. Ваш вопрос невероятно неясен. Ваше утверждение о том, что вы предоставили минимально воспроизводимый пример, демонстрирует только то, что вы не понимаете, что такое минимальный воспроизводимый пример.   -  person Peter Duniho    schedule 24.01.2021
comment
Вы говорите избавиться от объекта. Разве обновление, которое я сделал (см. все после «Как рекомендуется ниже»), не должно использовать dispose? Извините, если вам кажется, что это расплывчато. Но из-за отсутствия документации по DeviceClient у меня нет никакой дополнительной информации, на которую можно было бы опереться.   -  person NewCode    schedule 24.01.2021
comment
Я прошу прощения! Я не уверен, все в моем исходном посте должно содержать необходимый код, кроме необязательных пустяков о том, что GetProfiles_Click вызывается кнопкой с использованием оконных форм. Как вы чувствуете, чего не хватает?   -  person NewCode    schedule 24.01.2021
comment
@PeterDuniho Просто откройте новый проект (форма Windows), добавьте одну кнопку, скопируйте и вставьте ее в новый файл .cs, добавьте ссылки (как я упоминал выше), и все готово. Я только что попробовал еще раз и сработало! Не уверен, что, по вашему мнению, не хватает.   -  person NewCode    schedule 24.01.2021
comment
Существующее открытое TCP-соединение следует использовать повторно для последующих запросов, верно?   -  person Jesse de Wit    schedule 24.01.2021
comment
@Jesse de Wit: Ты первый, кто понял это. Короткий ответ, да! Это было мое предположение, и все работает так, как вы предлагаете, до тех пор, пока мне не нужно идти и настраивать RTP. Я удалил около тысячи строк кода с различными TCP-соединениями, которые закрывались и запускали другое, используя тот же объект. При каждом последующем вызове он закрывает TCP-соединение и начинает заново. Но затем, когда я перехожу к потоковому видео с помощью библиотеки c # VLC, RTP требует RTSP для настройки видеопотока (с использованием TCP). Это никогда не закрывает мое другое TCP-соединение и пытается запустить другое TCP-соединение.   -  person NewCode    schedule 24.01.2021