|
Как лучше организовать передачу большого объема данных через сокеты по TCP?
|
|||
---|---|---|---|
#18+
Возникла необходмость передавать большой объем данных (XML) через сокет. Сервер начинает передачу при приеме определенной команды - например, "getxmldata": Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42.
Клиент, подключившись к серверу, и отправив команду, начинает прием XML: Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39.
На небольших объемах данных все работает прекрасно, но вот на больших (для тестирования использовался XML, в виде файла весящий 4,5 Мб) происходит следующее: во время отсылки данных сервером в промежутке между очередным Socket.Send, у клиента в цикле получения stream.DataAvailable становится равным False (хотя на сервере все еще крутится цикл отправки данных), клиент выходит из цикла приема данных (получив лишь часть XML - где-то 1/3), и закрывает соединение с сервером, в результате чего последний вылетает по SocketException (Удаленный хост принудительно разорвал существующее подключение) при попытке отослать очередную порцию данных. Хотел сделать проверку в цикле на stream.DataAvailable тоже в течение какого-то промежутка (аналогично проверке после отсылки команды) - но может получиться так, что клиент отошлет две подряд команды достаточно быстро, и клиентский цикл, не дополучив до конца первый XML, начнет его дозаписывать данными начала второго XML - это не устраивает абсолютно. Второй вариант - дополнять данные маркером окончания передачи (каким-нибудь [EOF]), и проверять его наличие в очередной порции данных - но тогда при сбое сервера в процессе передачи клиенский цикл приема данных зависнет. Как тут лучше сделать? ... |
|||
:
Нравится:
Не нравится:
|
|||
17.06.2015, 10:30 |
|
Как лучше организовать передачу большого объема данных через сокеты по TCP?
|
|||
---|---|---|---|
#18+
WinterGraveyardКак тут лучше сделать? использовать самый обыкновенный HTTP протокол или просто вебсервис(WCF) и не заниматься низкоуровневым сокетом ... |
|||
:
Нравится:
Не нравится:
|
|||
17.06.2015, 12:01 |
|
Как лучше организовать передачу большого объема данных через сокеты по TCP?
|
|||
---|---|---|---|
#18+
Изопропил, если бы это можно было сделать - я бы так и поступил. Но в моем случае выбора нет: сервер, отдающий данные - стороняя программа, вышеприведенный код - на коленке смоделированная ситуация (и в случае сторонней программы возникают всё те же ошибки при тех же условиях). ... |
|||
:
Нравится:
Не нравится:
|
|||
17.06.2015, 12:06 |
|
Как лучше организовать передачу большого объема данных через сокеты по TCP?
|
|||
---|---|---|---|
#18+
В TCP данные приходят кусками, поэтому клиент не должен рвать соединение если принимать нечего. Надо просто ждать следующую порцию. Ищи способ определить что данные получены полностью. Если это XML - жди завершающий тэг. Добавь обработку разрыва соединения сервером и по причине плохой связи. Чтобы намертво не повисло при зависании сервера можно сделать какой-то таймаут после которого останавливать прием на клиенте. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.06.2015, 12:15 |
|
Как лучше организовать передачу большого объема данных через сокеты по TCP?
|
|||
---|---|---|---|
#18+
Т.е. в данном случае отпадают способы использования маркеров начала/окончания передачи - это я расфантазировался в процессе написания смоделированного сервера. Модификации подлежит только клиентский код, но вот как? Одна из идей - проверять уже считанные данные на предмет того, что они - well-formed XML, и если это так, то выходить из цикла чтения, а если не так, и NetworkStream.DataAvailable=false в течение некоторого времени, то считать, что был сбой в передаче, и делать попытку нового запроса данных. Единственное, что смущает - придется ведь уже всё считанное ранее целиком пытаться запихнуть в XmlReader, и на каждом шаге считывания объем проверяемых данных будет всё больше и больше - насколько это скажется на производительности в случае хотя бы вышеупомянутого тестового объема (4,5 Мб)? ... |
|||
:
Нравится:
Не нравится:
|
|||
17.06.2015, 12:15 |
|
Как лучше организовать передачу большого объема данных через сокеты по TCP?
|
|||
---|---|---|---|
#18+
WinterGraveyardХотел сделать проверку в цикле на stream.DataAvailable... Как тут лучше сделать?В протоколе всегда присутствует или размер передаваемого блока данных, или признак его окончания. Просто читай из сокета до конца блока, учитывая выше сказанное. В сокете установи соответствующий Read Timeout. WinterGraveyardНо в моем случае выбора нет: сервер, отдающий данные - стороняя программа.Если автор не удосужился добавить в протокол информацию о границах блоков данных, то можешь читать, пока не получишь валидный XML. Вероятно за один раз может прийти несколько XML документов, это следует тоже учитывать. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.06.2015, 12:22 |
|
Как лучше организовать передачу большого объема данных через сокеты по TCP?
|
|||
---|---|---|---|
#18+
WinterGraveyardЕдинственное, что смущает - придется ведь уже всё считанное ранее целиком пытаться запихнуть в XmlReader, и на каждом шаге считывания объем проверяемых данных будет всё больше и больше - насколько это скажется на производительности в случае хотя бы вышеупомянутого тестового объема (4,5 Мб)? Как вариант можно разбирать как строку. Найди открытие первого тэга и ожидай его закрытия. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.06.2015, 12:45 |
|
Как лучше организовать передачу большого объема данных через сокеты по TCP?
|
|||
---|---|---|---|
#18+
Dima TКак вариант можно разбирать как строку. Найди открытие первого тэга и ожидай его закрытия. Получилось даже немного проще: выяснилось, что закрывающий тэг всегда один и тот же, и он уникален в пределах документа. Поэтому получилось как-то так: Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46.
Спасибо. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.06.2015, 14:53 |
|
Как лучше организовать передачу большого объема данных через сокеты по TCP?
|
|||
---|---|---|---|
#18+
не хотелось новую тему создавать. вопрос первый - какой программой можно опросить тсп порт и узнать жив ли он? второе - какие есть хорошие инструкции как написать свой тсп клиент? ... |
|||
:
Нравится:
Не нравится:
|
|||
22.09.2015, 13:14 |
|
Как лучше организовать передачу большого объема данных через сокеты по TCP?
|
|||
---|---|---|---|
#18+
DoomUnitне хотелось новую тему создавать. вопрос первый - какой программой можно опросить тсп порт и узнать жив ли он? второе - какие есть хорошие инструкции как написать свой тсп клиент? А зря не хотелось. В Правилах же написано - "Один вопрос - одна тема". ... |
|||
:
Нравится:
Не нравится:
|
|||
22.09.2015, 13:53 |
|
Как лучше организовать передачу большого объема данных через сокеты по TCP?
|
|||
---|---|---|---|
#18+
DoomUnitкакой программой можно опросить тсп порт и узнать жив ли он? PsPing ... |
|||
:
Нравится:
Не нравится:
|
|||
22.09.2015, 22:46 |
|
|
start [/forum/topic.php?fid=20&fpage=76&tid=1401198]: |
0ms |
get settings: |
9ms |
get forum list: |
13ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
75ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
48ms |
get tp. blocked users: |
1ms |
others: | 13ms |
total: | 176ms |
0 / 0 |