Python/Windows: Oväntade tecken vid clientsocket.recv()

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
Användarvisningsbild
JimmyAndersson
Inlägg: 26566
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Python/Windows: Oväntade tecken vid clientsocket.recv()

Inlägg av JimmyAndersson »

OS: Windows XP.
Python: 2.7.6.

Som ni sett av ett par trådar så håller jag på att lära mig att skicka data
mellan ett python-script och ett C#-program.

Jag väntar med att göra C#-programmet och har valt att fokusera på python-scriptet först.
Python-scriptet agerar server. För att ansluta till det under testerna så använder jag Putty.


Scriptet körs i Windows "DOS-fönster", dvs cmd.exe.
Cmd kör ascii som teckenkodning som standard och detta har jag inte ändrat.
I Putty har jag testat med främst iso8859-1 men även UTF8 som teckenkodning.




Nu till själva problemet:

Att använda print("test") i Python-scriptet går fint oavsett om jag kör med UTF8 eller iso8859-1 i scriptet.
Dvs: Jag ser ordet 'test' i cmd-fönstret.

Men:
När jag i scriptet lyssnar på data från Putty
och printar ut det i cmd-fönstret så får jag oväntat resultat.
Detta oavsett om jag skrivit något i Putty-fönstret eller ej.



Det här är resultatet i cmd när jag just anslutit men inte skrivit något i Putty-fönstret:
ÿû▼ÿû ÿû↑ÿû'ÿý☺ÿû♥ÿý♥

(Beskrivning, tecken för tecken:
y med två prickar över.
u med ett ^ över.
En ifylld triangel med spetsen nedåt.
y med två prickar över.
u med ett ^ över.
mellanrum
y med två prickar över.
u med ett ^ över.
pil uppåt
osv...)


Jodå, jag ser mönstret (upprepningarna).
Det verkar som att clientsocket.recv() (se koden nedan) inte enbart tar emot
den data man som användare sänder, dvs det jag skriver i Putty-fönstret.


Jag har försökt ta reda på vad detta beror på, bl.a genom att googla på "clientsocket.recv()"
men jag har inte hittat något svar.
Delvis pga att Google är så idiotförklarande att det visar helt andra träffar än det man faktiskt sökte efter...
T.ex träff nr 1 vid sökning på "clientsocket.recv()" : http://docs.python.org/2/library/socket.html
Där nämns inte "clientsocket" överhuvudtaget.


Så i det här fallet är det trial&error från min sida.
Jag har t.ex testat att vända på steken och dekoda datan, men då får jag:
"UnicodeDecodeError: 'utf8' cannot decode byte 0xff in position 2: invalid start byte"




Nuvarande scriptet:

Kod: Markera allt

#!/usr/bin/python
# -*- coding: iso8859-1 -*-
from socket import *
import thread
import sys


print(sys.getdefaultencoding())  #Returnerar "ascii"
#exit()

data = ""

def handler(clientsocket, clientaddr):
    print("Server accepted connection from: ", clientaddr)
    
    global data
 
    try:
        data = clientsocket.recv(1024)  #Det är dessa tre rader
        data = data.decode('iso8859-1')  #som ger mig felet
        #data = data.decode('utf-8')
        print(data)                              #som jag beskriver i inlägget.
        
        if not data:
            pass
        elif data == "q":
            clientsocket.close()
        else:
            pass
            #print(data)
            #msg = "You sent me: %s" % data
            #clientsocket.send(msg)
    except KeyboardInterrupt: # Hanterar nar man trycker CTRL+C for att avbryta
        clientsocket.close()


if __name__ == "__main__":
    host = '127.0.0.1'
    port = 23
    buf = 1024
     
    addr = (host, port)
     
    serversocket = socket(AF_INET, SOCK_STREAM)
     
    serversocket.bind(addr)
     
    serversocket.listen(2)
 
    while 1:
        print("Server is listening for connections\n")
        clientsocket, clientaddr = serversocket.accept()
        thread.start_new_thread(handler, (clientsocket, clientaddr))
    serversocket.close()
Jag vet, koden är inte speciellt snygg och mycket grejer kan göra betydligt bättre.
Men jag tar ett steg i taget och ser hur saker uppför sig.
Genom detta kan jag lära mig och då justerar jag efter hand.



Jag vet inte riktigt vad jag ska fråga efter
eftersom jag inte vet exakt vad som är fel. :)

Någon som kan hjälpa mig att förstå vad som är fel?
Användarvisningsbild
adent
Inlägg: 4245
Blev medlem: 27 november 2008, 22:56:23
Ort: Utanför Jönköping
Kontakt:

Re: Python/Windows: Oväntade tecken vid clientsocket.recv()

Inlägg av adent »

Spontant känns det som din recv inte blockar och du skriver ut någon skit som råkar ligga i variablen och sen är det klart.

Det borde nog vara en loop runt recv på något vis också?

MVH: Mikael
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Python/Windows: Oväntade tecken vid clientsocket.recv()

Inlägg av sodjan »

Hur kör du Putty?
Ditt script verkar "serva" port 23 (d.v.s telnet).
Är det med avsikt? Kan det vara telnet "special commands" som du ser?
Har du kollat vilka hex värden som de där tecknen har?
Se t.ex: http://www.pcmicro.com/netfoss/telnet.html
Du kan stänga ner Putty så att den t.ex inte gör någon "negotiation".
Se "3.12.4 Passive and active Telnet negotiation modes" här:
http://www.yz.kiev.ua/www/etc/putty/Section3.12.html

Har du funderat på att köra telnetlib istället? Jag kör den och det
fungerar helt OK, i och för sig enbart som client...
Användarvisningsbild
JimmyAndersson
Inlägg: 26566
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Re: Python/Windows: Oväntade tecken vid clientsocket.recv()

Inlägg av JimmyAndersson »

Precis. Jag kör Putty som telnet-klient på port 23.

Om valet av port 23:
Det började med att jag ville ha en så enkel klient som möjligt,
så jag använde Windows inbyggda telnet-klient i ett cmd-fönster
mot port 23 som jag vet är öppen. Det satt i ryggmärgen helt enkelt.

Men efter ett tag bytte jag till Putty för att enklare kunna ansluta.
(Dubbelklicka istället för att skriva "o [ip-adress] [port]" t.ex.)
Och då fortsatte jag köra med port 23.
Jag hade förstås inte en tanke på att det fanns passive och active negotiation.




"Har du kollat vilka hex värden som de där tecknen har?"

Inte innan du frågade. :)
Jag visste inte var de kom ifrån och förväntade mig inte alls att det skulle vara från just telnet.
Så jag brydde mig inte om att kolla hex-värdena eftersom jag inte hade någon aning om var
jag skulle leta efter deras betydelse.

Men nu kollade jag de första, och visst var det telnet som pratade där. :)

hex: dec : telnet command
0x00FF : 255 : IAC (Interpret as command)
0x00FB : 251 : WILL (Indicates desire to begin performing, or confirmation that you're now performing, the indicated option. )
0x25BC : 9660
0x00FF : 255 : IAC
0x00FB : 251 : WILL
[tomt. Det finns ju flera tecken som ger utseendet av ett mellanslag, så jag har inget värde här.]
0x00FF : 255 : IAC
0x00FB : 251 : WILL
0x206D : 8301




'Du kan stänga ner Putty så att den t.ex inte gör någon "negotiation".'

Sådär ja, det blev bättre. Dvs nu får jag inte dessa tecken och
det jag skriver och skickar (oavsett riktning) kommer fram med rätt tecken.
Då var det alltså inget fel med med teckenkodning, som jag ett tag trodde.

Så den biten är alltså löst. Mycket trevligt, för jag kände mig helt vilse där innan.


Tack för tipset om telnetlib. Det ser väldigt smidigt ut. Ska testa det.



Adent:
"Det borde nog vara en loop runt recv på något vis också?"

Jodå. I exempelkoden som jag utgått från så var det en "while 1",
men jag ersatte det med en try/except för att slippa fastna totalt. :)
Jag ska göra en snyggare variant nu när jag vet att själva kommunikationen fungerar.


"Spontant känns det som din recv inte blockar"

Hur menar du med "blockar"? Berätta gärna mer, så jag vet ifall jag missat något. :)
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Python/Windows: Oväntade tecken vid clientsocket.recv()

Inlägg av sodjan »

> Tack för tipset om telnetlib. Det ser väldigt smidigt ut. Ska testa det.

När jag funderar lite mer så är det nog så att telnetlib enbart
fungerar som klient, d.v.s det är telnetlib som gör open/connect.

Däremot kan du ju använda ett python script med telnetlib för
dina tester istället för Putty! Lite enklare att automatisera.

Jag använder telnetlib för att skriva data till portar på en
terminalserver för att simulera en användare som läser
en streckkod med en handscanner. Typ:

Kod: Markera allt

$ python - 0965982700 20131900004

import sys
import telnetlib

artnr = sys.argv[1]
sernr = sys.argv[2]

tn = telnetlib.Telnet('10.32.137.39', 3004)

scan_data = chr(2) + '2400' + artnr + ',210' + sernr + chr(3)
tn.write(scan_data)

print tn.read_until(chr(3), 5)
Två portar på terminalservern är loopade (se bild) och scriptet ovan skriver
till en RS232 port och våran applikation läser från den andra. Smidigt...
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
JimmyAndersson
Inlägg: 26566
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Re: Python/Windows: Oväntade tecken vid clientsocket.recv()

Inlägg av JimmyAndersson »

Mycket smidigt! Den varianten skulle passa mig perfekt.

Rättare sagt: Det passar mitt behov perfekt. :)
För efter en fikapaus så gjorde jag ett python-script med telnetlib
och det blev mycket bättre jämfört med att använda Putty för detta.


Så nu kan jag börja jobba med resten av det förra python-scriptet.
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Python/Windows: Oväntade tecken vid clientsocket.recv()

Inlägg av sodjan »

:tumupp:
Kul att du hade användning för det...
Användarvisningsbild
adent
Inlägg: 4245
Blev medlem: 27 november 2008, 22:56:23
Ort: Utanför Jönköping
Kontakt:

Re: Python/Windows: Oväntade tecken vid clientsocket.recv()

Inlägg av adent »

För testning gillar jag netcat (nc brukar det heta i unixar) den kan vara både server och klient.

Tolkade din beskrivning som att skräpet var det enda som kom fram åt det hållet.

Nu vet jag inte hur mycket som finns i Python, men i C kan man anropa recv blockande eller icke-blockande.
Man kan använda select() för att vänta på data på flera socketar samtidigt. Eller så kan man kan köra trådat, det kanske är mest naturligt.

MVH: Mikael
Användarvisningsbild
JimmyAndersson
Inlägg: 26566
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Re: Python/Windows: Oväntade tecken vid clientsocket.recv()

Inlägg av JimmyAndersson »

Jag hade visst glömt svara.

Jag hade tänkt trådat först, men det blev select()
och nu när jag har lärt mig lite mer så förstår jag precis hur du menar med blockande/icke-blockande. :)
Användarvisningsbild
007sweden
Inlägg: 3500
Blev medlem: 3 mars 2005, 20:18:12
Skype: oo7sweden

Re: Python/Windows: Oväntade tecken vid clientsocket.recv()

Inlägg av 007sweden »

Skräpet som du ser är som sagt telnets kontrollkoder, du kan prova välja "raw" i putty för att få en "rå" anslutning utan telnet-"overhead". Ett tips är ju också att kolla på det du skickar till/från skript med etherdetect eller wireshark eller annan valfri nätverkssniffer, så hjälper det att debugga *var* saker händer. :)
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Python/Windows: Oväntade tecken vid clientsocket.recv()

Inlägg av sodjan »

Jag sätter även "Force off" på "Local echo" och "Local line editing" när jag
kör telnet mot något som inte är en "normal" telnet-server implementation.
T.ex reverse-telnet mot terminal servers.
Skriv svar