Я прошу прощения за этот длинный пост.Я сделал его настолько маленьким, насколько это возможно, но все еще передавал проблему.
Хорошо, это сводит меня с умаУ меня есть клиентская и серверная программа, обе на C #.Сервер отправляет данные клиенту через Socket.Send ().Клиент получает данные через Socket.BeginReceive и Socket.Receive.Мой псевдопротокольный протокол выглядит следующим образом: Сервер отправляет двухбайтовое (короткое) значение, указывающее длину фактических данных, за которыми немедленно следуют фактические данные.Клиент считывает первые два байта асинхронно, преобразует байты в короткий и немедленно считывает столько байтов из сокета синхронно.
Теперь это работает нормально один цикл каждые несколько секунд или около того, но когда я увеличиваю скорость, все становится странным.Кажется, что клиент будет случайным образом читать фактические данные, когда он пытается читать с двухбайтовой длины.Затем он пытается преобразовать эти два произвольных байта в короткий, что приводит к совершенно неправильному значению, вызывающему сбой.Следующий код взят из моей программы, но обрезан так, чтобы показывать только важные строки.
Метод отправки на стороне сервера:
private static object myLock = new object();
private static bool sendData(Socket sock, String prefix, byte[] data)
{
lock(myLock){
try
{
// prefix is always a 4-bytes string
// encoder is an ASCIIEncoding object
byte[] prefixBytes = encoder.GetBytes(prefix);
short length = (short)(prefixBytes.Length + data.Length);
sock.Send(BitConverter.GetBytes(length));
sock.Send(prefixBytes);
sock.Send(data);
return true;
}
catch(Exception e){/*blah blah blah*/}
}
}
Метод получения данных на стороне клиента:
private static object myLock = new object();
private void receiveData(IAsyncResult result)
{
lock(myLock){
byte[] buffer = new byte[1024];
Socket sock = result.AsyncState as Socket;
try
{
sock.EndReceive(result);
short n = BitConverter.ToInt16(smallBuffer, 0);
// smallBuffer is a 2-byte array
// Receive n bytes
sock.Receive(buffer, n, SocketFlags.None);
// Determine the prefix. encoder is an ASCIIEncoding object
String prefix = encoder.GetString(buffer, 0, 4);
// Code to process the data goes here
sock.BeginReceive(smallBuffer, 0, 2, SocketFlags.None, receiveData, sock);
}
catch(Exception e){/*blah blah blah*/}
}
}
Код на стороне сервера для надежного воссоздания проблемы:
byte[] b = new byte[1020]; // arbitrary length
for (int i = 0; i < b.Length; i++)
b[i] = 7; // arbitrary value of 7
while (true)
{
sendData(socket, "PRFX", b);
// socket is a Socket connected to a client running the same code as above
// "PRFX" is an arbitrary 4-character string that will be sent
}
Глядя на приведенный выше код, можно определить, что сервер навсегда отправит число 1024, длину общих данных, включая префикс, как короткий (0x400), за которым следует «PRFX» в двоичном коде ASCII, за которым следует набор из 7 (0x07).Клиент будет всегда читать первые два байта (0x400), интерпретировать это как 1024, сохранять это значение как n, а затем читать 1024 байта из потока.
Это действительно то, что он делает для первых 40 или около того итераций, но, спонтанно, клиент читает первые два байта и интерпретирует их как 1799, а не 1024!1799 в шестнадцатеричном виде - это 0x0707, что является двумя последовательными семерками !!!Это данные, а не длина!Что случилось с этими двумя байтами?Это происходит с любым значением, которое я ввел в байтовый массив, я просто выбрал 7, потому что легко увидеть корреляцию с 1799.
Если вы все еще читаете к этому моменту, я приветствую вашу преданность делу.
Некоторые важные наблюдения:
- Уменьшение длины b увеличит число итераций до возникновения проблемы, но не предотвратит возникновение проблемы
- Добавление значительной задержки междукаждая итерация цикла может предотвратить возникновение проблемы
- Это НЕ происходит при использовании клиента и сервера на одном хосте и подключении через адрес обратной связи.
Как уже упоминалось, это сводит меня с ума!Я всегда в состоянии решить свои проблемы с программированием, но это полностью поставило меня в тупик.Поэтому я здесь прошу любых советов или знаний по этому вопросу.
Спасибо.