|
|
|
Подскажите по сокетам
|
|||
|---|---|---|---|
|
#18+
Всем привет! Все копаюсь в сокетах и конкретно в передаче файлов через них)) В данном случае клиент передает файл на сервер. Не понимаю в чем дело: хочется после приема файла отправлять в ответ сообщение, что файл получен, но дело в том, что файл передается нормально, а дальше все висит. В режиме дебага на сервере я не дохожу до строки pw.println(1); а на клиенте все висит на System.out.println(br.readLine()); Самое интересное, если убрать на клиенте это самое System.out.println(br.readLine()); то все ок, сервер pw.println(1); проходит и завершает итерацию цикла. В чем моя ошибка ? Спасибо! Есть сервер: Код: java 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. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. И клиент: Код: java 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. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.12.2015, 11:51 |
|
||
|
Подскажите по сокетам
|
|||
|---|---|---|---|
|
#18+
Ошибка в протоколе. readLine() вычитывает всё до переноса строки или конца стрима. Конец стрима это -1. Севрер отправляет файл, затем дописывает к нему единицу. Откуда клиенту знать что это единица конец файла, а не сам файл? Шли -1. Почему для сокетов try with resource используется, а для IO - нет? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.12.2015, 11:57 |
|
||
|
Подскажите по сокетам
|
|||
|---|---|---|---|
|
#18+
bobo96, И нужно ещё понимать что java.io это блокирующее IO. Если клиент читает данные, а сервер их не шлет, то поток блокируется. В вашей терминологии " на клиенте все висит". Нет не всё, "висит" только поток, который использует блокирующее IO. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.12.2015, 11:59 |
|
||
|
Подскажите по сокетам
|
|||
|---|---|---|---|
|
#18+
BlazkowiczСеврер отправляет файл, затем дописывает к нему единицу. Откуда клиенту знать что это единица конец файла, а не сам файл? Немного не так: Клиент отправляет файл, сервер его принимает и шлет обратно на клиент единицу. OutputStream на сервере при этом же ничем не занят или я что-то путаю ? BlazkowiczПочему для сокетов try with resource используется, а для IO - нет? На скорую руку все накидал, мне важно в механизме работы сокетов разобраться :) BlazkowiczИ нужно ещё понимать что java.io это блокирующее IO. Если клиент читает данные, а сервер их не шлет, то поток блокируется. В вашей терминологии " на клиенте все висит". Нет не всё, "висит" только поток, который использует блокирующее IO. Я это понимаю, криво просто выразился. Клиент стоит на br.readLine() и ждет, пока туда что-то прилетит. В общем я, видимо, совсем дремучий, но мне до сих пор не понятно, где ошибка. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.12.2015, 12:09 |
|
||
|
Подскажите по сокетам
|
|||
|---|---|---|---|
|
#18+
bobo96Немного не так: Клиент отправляет файл, сервер его принимает и шлет обратно на клиент единицу. OutputStream на сервере при этом же ничем не занят или я что-то путаю ? Ок. Сервер шлет 1. А клиент через readLine ждет конца стрима или строки. Как вы думаете, 1 это конец стрима или строки? Ну, шлите "1\n", чтобы не висело. Только учтите что readLine(), возможно, хочет перенос строки локальной системы, что под виндой \r\n. bobo96На скорую руку все накидал, мне важно в механизме работы сокетов разобраться :) Ну, да, а другим в этом говнокоде разбираться теперь? bobo96В общем я, видимо, совсем дремучий, но мне до сих пор не понятно, где ошибка. Ошибка в том что клиент читает до тех пор пока не получит то чего хочет. А сервер этого не шлет. Если вы во время "зависания" остановите приложение и посмотрите в дебаге, то, возможно во фрейме readLine() увидите в буфере свою единицу. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.12.2015, 12:25 |
|
||
|
Подскажите по сокетам
|
|||
|---|---|---|---|
|
#18+
Дошло. Даже заработало :) Спасибо :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.12.2015, 12:55 |
|
||
|
Подскажите по сокетам
|
|||
|---|---|---|---|
|
#18+
Дорогие программисты :) Продолжу, с вашего позволения. Еще пара вопросов: 1. При приеме файла функция read(byte b); не возвращает -1, следовательно из цикла while ((count = socket.getInputStream().read(bytes)) != -1) { ... } выйти невозможно. Почему не возвращается -1 ? 2. Чутка облагородил писанину. Это все еще говнокод ? :) Еще раз заранее благодарю! Сервер: Код: java 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. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. Клиент: Код: java 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. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.12.2015, 07:34 |
|
||
|
Подскажите по сокетам
|
|||
|---|---|---|---|
|
#18+
bobo961. При приеме файла функция read(byte b); не возвращает -1, следовательно из цикла while ((count = socket.getInputStream().read(bytes)) != -1) { ... } выйти невозможно. Почему не возвращается -1 ? -1 это конец InputStream, а не файла. Для того чтобы на одной стороне получить -1, на второй стороне нужно закрыть OutputStream. bobo962. Чутка облагородил писанину. Это все еще говнокод ? :) Зачем перенос после каждой строки? b - не читаемое имя переменной. Зачем самому писать\читать через буфер, когда давно уже существуют BufferedInput/OutputStream и Apache Commons IOUtils? Логика сервера кривая. Мы вычитывает строку. Проверяем, на соответствие какому-то сообщению и если не соответствует, вычитываем новую строку. А что с данными который были в той строке?? Мы их выкидываем? else пишется в той же строке что и закрывающая скорбка, а не через 2 строки после неё. if (total == fileSize) - в таких условиях принято писать >=, чтобы в случае привышения размера из-за какой-либо баги мы не ушли в бесконечный цикл. Зачем серверу 3 одинаковых catch (IOException e) {e.printStackTrace();}, если можно обойтись одним? Код: java 1. 2. 3. Просто берите имя файла из args[0]. PrintWriter и BufferedReader используют платформо зависимый перенос строки. Если запустить клиент и сервер на разных платформах, то протокол может сломаться. Комбинировать чтение\запись из Buffered потока и его внутреннего потока - пагубно. Часть данных может осесть в буфере, в запись\чтение потом идут напрямую мимо этого буфера и ломают протокол. В целом, Reader/Writer для работы с сокетами используется редко. Потому что для текста уже давно изобретён HTTP. Сообщения "sendFile", "1", "dscn" надо из магических констант вынести в общие поля для сервера и клиента. Чтобы нигде никакая опечатка не проскочила. Да, и код понятнее будет, если у тебя все сообщения протокола в виде Enum или его аналога. К прочтению настоятельно рекомендуется Robert C Martin - Clean Code ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.12.2015, 09:09 |
|
||
|
Подскажите по сокетам
|
|||
|---|---|---|---|
|
#18+
Спасибо! Узнал МНОГО нового :) Но остались непонятные моменты BlazkowiczЗачем самому писать\читать через буфер, когда давно уже существуют BufferedInput/OutputStream Тут вот не понял, что имеется в виду. Все примеры, которые находил в интернетах, так же точно и выглядят, как мой. Например: https://www-01.ibm.com/support/knowledgecenter/ssw_i5_54/rzaha/sslcex04.htm Часть кода: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. Чем это принципиально отличается от того, как сделано у меня ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.12.2015, 12:02 |
|
||
|
Подскажите по сокетам
|
|||
|---|---|---|---|
|
#18+
bobo96Тут вот не понял, что имеется в виду. Код: java 1. 2. 3. 4. Внутри BufferedInputStream уже есть буфер, который работает аналогичным образом. Поэтому код копирования можно существенно упростить копируя данный по 1 байту в виде int, вместо byte[]. Да, это будет немного медленее, но не на столько медленнее чтобы на вашем примере это было заметно. Вот если буферизации не будет вообще, тогда разница будет видна невооруженным глазом. Опять, же, если мы копируем на диск или читаем из него, у нас есть вот такой класс http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html bobo96Все примеры, которые находил в интернетах, так же точно и выглядят, как мой. Этим грешат многие примеры. bobo96Чем это принципиально отличается от того, как сделано у меня ? Есть такое понятие Boilerplate code Многие вещи можно и нужно делать проще. Но при этом, конечно же, следить чтобы не упала читаемость. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.12.2015, 12:37 |
|
||
|
|

start [/forum/topic.php?fid=59&tid=2124515]: |
0ms |
get settings: |
9ms |
get forum list: |
15ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
151ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
63ms |
get tp. blocked users: |
2ms |
| others: | 220ms |
| total: | 481ms |

| 0 / 0 |
