Связь с клиентом и сервером через сокеты
Итак, я написал код, чтобы я мог общаться с сервером и клиентом.
- Первый вопрос: как сервер определяет, что он взаимодействует с реальным клиентом, а не с кем-то еще, кто использует порт, я слышал, что браузеры проверяют серверы, используя хеширование SHA.
- Второй вопрос касается наилучшего способа отправки и получения данных в переменных, а также определения того, что есть что, потому что текущий метод разделения данных не выглядит очень элегантным.
Код на стороне сервера для получения и отправки данных:
NetworkStream NetStream1 = TCPSocket.GetStream();
NetStream.Read(Buffer, 0, Buffer.Length);
ReceivedData = System.Text.Encoding.ASCII.GetString(Buffer);
string[] splitter = ReceivedData.Split('-');
Variable1 = splitter[0];
Variable2 = splitter[1];
//send response
SendBuffer = Encoding.ASCII.GetBytes(ResultINT1+"-"+ResultINT2);
NetStream.Write(SendBuffer, 0, SendBuffer.Length);
NetStream.Flush();
Код клиента для отправки и получения
NetworkStream SendStream = ClientSocket.GetStream();
byte[] SendBuffer = System.Text.Encoding.ASCII.GetBytes(V1+"-"+V2);
SendStream.Write(SendBuffer, 0, SendBuffer.Length);
SendStream.Flush();
//response
SendStream.Read(RecieveBuffer, 0, RecieveBuffer.Length);
string ResultString = System.Text.Encoding.ASCII.GetString(RecieveBuffer);
string[] splitted = ResultString.Split('-');
int R1 = Convert.ToInt32(splitted[0]);
int R2 = Convert.ToInt16(splitted[1]);
4 ответа
Ваш первый вопрос касается аутентификации, которая является огромной темой и имеет много возможных реализаций, хотя я не совсем уверен, что вы подразумеваете под "кем-то еще, кто использует порт". Ваш сервер всегда должен быть на одном и том же порту - так клиент определяет сервис.
Что касается вашего второго вопроса, то снова есть много возможностей, но я бы предположил, что самым простым для новичка будет использование XmlSerializer и простой конверт сообщения.
- Создайте класс XmlSerializable либо просто с помощью простых общедоступных свойств, либо, возможно, с помощью XmlElementAttribute, XmlRootAttribute и т. Д.
- Сериализация в MemoryStream
- Запишите байты из потока памяти, обернутого в конверт (см. Позже)
- Получите полный конверт в байтовый массив.
- построить MemoryStream из байтового массива
- Используйте XmlSerializer, чтобы восстановить копию вашего исходного объекта.
Конверт имеет решающее значение. Самый простой - это просто двоичная длина сериализованного объекта. Большинство протоколов обычно расширяют это с помощью CRC для обработки возможного повреждения, но поскольку Ethernet использует сильный CRC, а TCP является надежным транспортным средством (хотя и со слабым CRC), которое обычно является избыточным. Ключевым моментом, который пропускают новички, является то, что TCP является потоковым протоколом, а не протоколом, основанным на сообщениях, таким образом, для отправителя вполне возможно сделать одну запись, скажем, 1000 байтов, и, тем не менее, получатель получает это как количество меньших кусков. Вот почему вам нужен какой-то способ определения конца сообщения, например, использование длины и почему получателю необходимо накапливать полученные куски до тех пор, пока не будет получено полное сообщение (и, возможно, часть следующего), которое может быть десериализовано.
Это может показаться сложным, но, к сожалению, на уровне TCP это не становится проще:(
- Предоставить некоторый механизм аутентификации
- Используйте какой-нибудь сериализатор.
Первый вопрос: как сервер определяет, что он взаимодействует с реальным клиентом, а не с кем-то еще, кто использует порт, я слышал, что браузеры проверяют серверы, используя хеширование SHA.
Сервер может идентифицировать разных клиентов по их IP-адресам. Увидеть StreamReader.ReadToEnd
Второй вопрос касается наилучшего способа отправки и получения данных в переменных, а также определения того, что есть что, потому что текущий метод разделения данных не выглядит очень элегантным.
Это зависит от архитектуры вашего протокола, но переносимый способ обмена значениями в сети - это сохранять их в текстовом формате (таким образом, нет проблем с порядком байтов, размером шрифта...).
Сказал, что, будьте осторожны с вашим разделителем переменных: '-'
может быть трудно использовать с отрицательными числами, ' '
или же ';'
более распространены.
Возможно, вы захотите определить некоторый протокол связи - текстовый протокол будет наиболее простым для начала - затем вы можете читать и записывать "команды", каждая из которых находится на отдельной строке.
Во-первых, произойдет "рукопожатие", когда клиент отправит что-то вроде "HELLO my-awesome-protocol-v1\n", а сервер ответит аналогичным образом. Таким образом, вы будете уверены, что другой человек является клиентом, который понимает протокол, или вы можете закрыть соединение, которое не реализует протокол.
Тогда может быть какой-то способ отправки значений переменных с помощью команд типа "VAR variableName 123.45\n". Вы можете прочитать https://en.wikipedia.org/wiki/Text-based_protocol и посмотреть http://www.ncftp.com/libncftp/doc/ftp_overview.html для вдохновения.