Найти - Пользователи
Полная версия: socket и Линукс
Начало » Python для новичков » socket и Линукс
1 2
nauman
Просветите пожалуйста. Есть скрипт сервер и клиент, соединение через сокет. Серверная часть работает на Виндовс XP. Суть проблемы скрипт клиент полностью работает только под виндой ХР, под Линуксом появляется ошибка. Сразу оговорюсь, думаю, что проблема в линуксе, каоето ограничение, так как с разных машин получаю один и тотже размер 1448. Привожу пример:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.0.24', 54917))
print 'Serv on address: ', s.getpeername()
for i in range(3):
content = s.recv(300000)
print len(content)
ima=Image.open(StringIO.StringIO(content)).quantize(colors=96, method=1)
Serv on address:  ('192.168.0.24', 54917)
1448
Traceback (most recent call last):
File "/media/truecrypt1/socket_client.py", line 20, in <module>
ima=Image.open(StringIO.StringIO(content)).quantize(colors=96, method=1)
File "/usr/lib/python2.6/dist-packages/PIL/Image.py", line 717, in quantize
self.load()
File "/usr/lib/python2.6/dist-packages/PIL/ImageFile.py", line 198, in load
s = read(self.decodermaxblock)
File "/usr/lib/python2.6/dist-packages/PIL/PngImagePlugin.py", line 391, in load_read
cid, pos, len = self.png.read()
File "/usr/lib/python2.6/dist-packages/PIL/PngImagePlugin.py", line 96, in read
len = i32(s)
File "/usr/lib/python2.6/dist-packages/PIL/PngImagePlugin.py", line 44, in i32
return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24)
IndexError: string index out of range
Этот код нормально работет под виндой XP, под Ububtu 10.04 c выше описанной ошибкой. В обоих случаях Python 2.6.
tmp_a6367100
Суть проблемы скрипт клиент полностью работает только под виндой ХР, под Линуксом появляется ошибка.
:-)

если это единственная информация которая нам доступна – то это малова-то
tmp_a6367100
что находиться на строчке 20 ? в приведённом вами коде нет никаких
ima=Image.open(StringIO.StringIO(content)).quantize(colors=96, method=1)
но ошибка именно там…

********************************************************************************

..и вообще – зачем вы делаете – s.recv(300000) ?

вы используете слишком низкоуровневые операции на сокетах!


операции могут быть и на порядок выше .

********************************************************************************

и вообще:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # плакал IPv6 горькими слезами, 
# ... потомучто злой хзяин (программист) забыл выполнить http://docs.python.org/library/socket.html#socket.getaddrinfo
(но это уже не относитсья к проблеме)
tmp_a6367100
tmp_a6367100
операции могут быть и на порядок выше .
затем делайте http://docs.python.org/library/stdtypes.html#file.read или сразу подставляйте файловый-объект внутрь нужной функции
nauman
tmp_a6367100
что находиться на строчке 20 ? в приведённом вами коде нет никаких
Код:

ima=Image.open(StringIO.StringIO(content)).quantize(colors=96, method=1)

но ошибка именно там…
Ошибка там только потому, что Image получает не полную, урезанную возможно Линуксом, информацию. Этот же скрипт под виндой работает без исключений. 1448 - это количество знаков в получаемой строке, при любом раскладе. На самом деле их передается больше. Для ясности картины чуть изменил первый пост. ima, ему присваивается объект Image, далее пишется в файл на диск. Объект передается не весь поэтому он сообщает это в листинге возникших исключений.
tmp_a6367100
Т.е. вы предлагаете последовательно получать по 1448 символов, пока не получит всю строку?
Это может и быть выходом в данной проблеме, но все же, хотелось бы узнать как убрать ограничение OC.

IPv6 мне в данном случае вообще не нужен.
Серверную часть менять уже не могу.
tmp_a6367100
nauman
IPv6 мне в данном случае вообще не нужен.
пользователей вашей программы пожалейте :-)
tmp_a6367100
> Т.е. вы предлагаете последовательно получать по 1448 символов, пока не получит всю строку?

да. так как вы s.recv – это НИЗКОУРОВНЕВАЯ операция…

тоесть если хотите использовать именно эту функцию то нужно возиться с “атамими и малекулами” (в переносном смысле) :-)


> Это может и быть выходом в данной проблеме, но все же, хотелось бы узнать как убрать ограничение OC.

это не ограничение ОС, а правильная её работа.. непонимаю что тут убирать… recv() не обязана получать столько байт сколько вы хотите .

если хотите получать именно столько байт сколько заказываете получать – то используйте другие функции . например как уже писал выше:

f = s.makefile(“rb”)
content = f.read(300000)
Ed
Суть проблемы скрипт клиент полностью работает только под виндой ХР, под Линуксом появляется ошибка.
Когда скрипт клиент успешно работает, то он запускается на той же виндовой машине, что и сервер? Если да, то попробуйте запустить его на другой виндовой машине.
Каков размер передаваемых данных с сервера клиенту? В вашем случае это content, какова его длина?
nauman
Ed
Суть проблемы скрипт клиент полностью работает только под виндой ХР, под Линуксом появляется ошибка.
Когда скрипт клиент успешно работает, то он запускается на той же виндовой машине, что и сервер? Если да, то попробуйте запустить его на другой виндовой машине.
Каков размер передаваемых данных с сервера клиенту? В вашем случае это content, какова его длина?
Серверная часть работает на нескольких удаленных компах в пределах локальной сети, везде стоит XP.
Создается скриншёт экрана, и передается по сети к клиенту, размер от файла к файлу отличаетя, в среднем это 70 Кб. Под линуксом к клиенту поступает строго 1448. Кстати проделывал это на гостевой winXP под VirtualBox в том же Ubuntu, результат тотже, линукс рубит размер. На всякий случай фаервол отключал.
Kogrom
Пытался разобраться…
Можно пытаться увеличить буфер:

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
SEND_NUMBER = 300000
s.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, SEND_NUMBER)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, SEND_NUMBER)
Правда, у меня с ходу вышло увеличить только до 262144 байт.

А вообще, читайте статьи, типа:

http://www.ibm.com/developerworks/ru/library/l-hisock/

вроде бы там говорится, как ещё больше увеличить буфер.

Когда у меня не было под рукой документации и надо было такое считать, то я действовал с помощью склейки, посылая (и принимая) кадры по 256 байт. Первый байт нес в себе размер кадра. Правда я грешил на слабость uCLinux…
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB