tags:

views:

222

answers:

2

I'm trying to write a simple socket-based client in Python that will connect to a telnet server. I can test the server by telnetting to its port (5007), and entering text. It responds with a NAK (error) or an AK (success), sometimes accompanied by other text. Seems very simple.

I wrote a client to connect and communicate with the server, but it hangs on the first attempt to read the response. The connection is successful. Queries like getsockname and getpeername are successful. The send command returns a value that equals the number of characters I'm sending, so it seems to be sending correctly. But in the end, it always hangs when I try to read the response.

I've tried using both file-based objects like readline and write (via socket.makefile), as well as using send and recv. With the file object I tried making it with "rw" and reading and writing via that object, and later tried one object for "r" and another for "w" to separate them. None of these worked.

I used a packet sniffer to watch what's going on. I'm not versed in all that I'm seeing, but during a telnet session I can see my typed text and the server's text coming back. During my Python socket connection, I can see my text going to the server, but packets back don't seem to have any text in them.

Any ideas on what I'm doing wrong, or any strategies to try?

Here's the code I'm using (in this case, it's with send and recv):

#!/usr/bin/python

host = "localhost"
port = 5007
msg = "HELLO EMC 1 1"
msg2 = "HELLO"

import socket
import sys

try:
    skt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, e:
    print("Error creating socket: %s" % e)
    sys.exit(1)

try:
    skt.connect((host,port))
except socket.gaierror, e:
    print("Address-related error connecting to server: %s" % e)
    sys.exit(1)
except socket.error, e:
    print("Error connecting to socket: %s" % e)
    sys.exit(1)

try:
    print(skt.send(msg))
    print("SEND: %s" % msg)
except socket.error, e:
    print("Error sending data: %s" % e)
    sys.exit(1)


while 1:
    try:
        buf = skt.recv(1024)
        print("RECV: %s" % buf)
    except socket.error, e:
        print("Error receiving data: %s" % e)
        sys.exit(1)
    if not len(buf):
        break
    sys.stdout.write(buf)

Oh, in case it's useful, here's an example telnet session done manually:

ubuntu:~/mac/python$ telnet localhost 5007
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
HELLO EMC 1 1
HELLO ACK EMCNETSVR 1.1

The first 'HELLO' line is what I typed, the second one is the response.

A: 

You need to flush the socket right after the send, to force the TCP stack to actually send the data. Otherwise it will wait for more data to send, in order to fill a packet effectively. While you are waiting for a response from the server nothing has actually been sent yet.

calmh
I tried a flush() on the file object version, with no change in behavior. There doesn't seem to be a flush() method for socket that works with socket.write (?).
mix
+2  A: 

You probably need to terminate your msg with some kind of "line-ending characters" -- perhaps \r\n, perhaps just one of the two. When you're in telnet, didn't you terminate your typed text by hitting a Return or Enter key? In the Python code, you're not doing the equivalent of that.

Alex Martelli
fabulous, the \r did the trick! i had tried \n earlier (didn't work) but wasn't aware of \r. the flush wasn't required either. thanks!
mix
turned out i needed the \r\n, not just \r. \r works in some cases, but not in all, which was confusing. \n by itself worked in none.
mix