Рейтинг:
6
nie_trzeba
Я бы с удовольствием не привязывал клиента к определенному порту, но мой босс хотел, чтобы это сообщение всегда отправлялось с одного конкретного порта :/
Я прочитал и попытался настроить опцию сокетов с помощью Разъем.LingerState() как вы мне советуете, и поместите его в любом месте моего кода, но, к сожалению, это не помогает. Я Разъем.LingerState.LingerTime = 0 но в любом случае это мне не помогло. Серьезно, я не знаю, что еще с этим делать.
Jochen Arndt
Жаль, что это не сработало. Он должен быть установлен сразу после создания сокета (используя true и timeout zero).
Другим решением может быть использование молотка:
Прекратите использование winsocks с помощью вызова API WSACleanup () с помощью PInvoke. Это могло бы освободить сокет, но было бы уродливым решением.
Вы также можете спросить своего босса, почему это должен быть фиксированный порт. Я думаю, что он не может дать вам разумного ответа. Но он-босс.
nie_trzeba
Действительно странно, потому что так много вещей, которые помогают другим, не помогли в моем случае. Может, просто руки растут не с той стороны ? :)
Я никогда не слышал об этом, поэтому погуглил об этом и попытался сделать точно так же, как по этой ссылке https://www.experts-exchange.com/questions/21014265/PInvoke-winsock-WSAStartup-and-WSACleanup-in-c.html но, к сожалению, это тоже не помогло.
Я спросил своего босса, зачем ему это нужно, и его ответ был вполне разумным. Дело в том, что мы делаем сервер, который потом будем продавать компаниям, и он боится, что на каком-то ПК брандмауэр может заблокировать некоторые порты, и система не сможет выбрать правильный без привязки, и сообщение не сможет быть отправлено. Я действительно плохо разбираюсь в брандмауэрах или т. д., Так что это было похоже на правду для меня.
В любом случае, большое спасибо за ваши попытки и потраченное впустую время на меня, это действительно круто :)
Jochen Arndt
Я ожидал такой "причины".
Это не то, как работает обычный TCP. Сервер должен использовать фиксированный номер порта, на котором он прослушивает. Это должно быть исправлено, потому что клиент должен это знать. Но нет никаких причин использовать фиксированный номер порта на клиенте.
Брандмауэры используют "проверку состояния". Это означает, что они отслеживают номера портов (и другую информацию) исходящих исходных пакетов. Если есть пакеты, поступающие в порт, который отслеживается (принадлежит к связи, которая была инициирована ранее), им разрешается пройти.
Таким образом, только порт, используемый сервером, должен быть разрешен во входных настройках брандмауэра сервера. Настройки брандмауэра на клиенте не заботятся о портах установленного соединения.
Они могут быть сбиты с курса и настроены на более строгие ограничения. Но это не ваша проблема, если кто-то неправильно настроит свой брандмауэр таким образом. Когда он не сможет подключиться к вашему серверу, он, вероятно, также не сможет использовать веб-браузер или почтовый клиент.
nie_trzeba
Большое вам спасибо за ваш ответ! Я постараюсь описать и доказать это своему боссу. Спасибо вам за вашу помощь !
nie_trzeba
Извините еще раз, я хочу задать еще один вопрос, если мы не свяжем наш клиентский сокет, то как сервер узнает, куда отправить ответное сообщение ?
Jochen Arndt
Метод connect () выполняет неявную привязку () к любому адресу/порту, если функция bind () не вызывалась ранее. То есть ОС выберет интерфейс в соответствии с IP-адресом назначения с помощью таблицы маршрутизации и выберет высокий номер порта.
Сервер сохраняет IP-номер клиента при приеме входящего соединения. Номера портов являются частью заголовков TCP. Например, см. https://en.wikipedia.org/wiki/Transmission_Control_Protocol.
Но вы не должны беспокоиться об этом. Все это обрабатывается операционной системой и API сокета.
nie_trzeba
Большое спасибо! И еще раз, пожалуйста (обещаю!), я постараюсь связывать() метод снова по протоколу UDP, там есть Отправить() метод, который отправляет сообщение без Подключить(), поэтому я попытался Связывать() это к указанному порту только один раз, в начале, а затем просто вызовите Отправить() метод, и я не знаю, но похоже, что он работает! Я имею в виду, что после каждой отправки я Райт на консоли LocalEndPoint, и он показывает мне тот, который я указываю при привязке. Как вы думаете, моя программа сейчас работает нормально и действительно ли она отправляет сообщения с одного порта ? Вот код:
static void UDPMessage()
{
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("10.11.2.147"), Convert.ToInt32("17000"));
Socket s = new Socket(endPoint.Address.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint myPoint = new IPEndPoint(IPAddress.Parse("10.11.2.147"), Convert.ToInt32("61000"));
try
{
byte[] msg = Encoding.Unicode.GetBytes("hello");
s.Bind(myPoint);
s.SendTo(msg, SocketFlags.None, endPoint);
Console.WriteLine(s.LocalEndPoint.ToString());
s.SendTo(msg, SocketFlags.None, endPoint);
Console.WriteLine(s.LocalEndPoint.ToString());
s.SendTo(msg, SocketFlags.None, endPoint);
Console.WriteLine(s.LocalEndPoint.ToString());
s.SendTo(msg, SocketFlags.None, endPoint);
Console.WriteLine(s.LocalEndPoint.ToString());
}
catch
{
}
finally
{
Console.ReadLine();
}
}
Jochen Arndt
UDP-это не TCP. Это совершенно другое. Он не использует соединения или какие-либо квитирования и восстановления ошибок. Это включает в себя то, что сокет действительно закрыт при вызове метода Close ().
С UDP использование фиксированного исходного порта имеет смысл. В противном случае номер порта должен быть отправлен в качестве полезной нагрузки на сервер, чтобы он знал, на какой порт должен быть отправлен ответ. Реализация такого подхода-это определение вашего собственного вида протокола.
Но прежде чем использовать UDP вы должны подумать о недостатках:
- Пакеты могут потеряться (с TCP они обижаются)
- Пакеты могут поступать не по порядку (обрабатываются TCP)
- Требуется определение протокола для 2-сторонней связи
nie_trzeba
О, хорошо, я понял! Большое спасибо за все Ваши советы! Я постараюсь подробнее изучить этот протокол. Спасибо!