2

I am learning socket programming and python. I need to create a client that sends a command to a server (list or get ). The server then validates the command. My client program can display "list" or "get" , but it doesn't show the error message when I enter other things.
Also, it only works one time; when I enter a different command after receiving a reply from the server, it gives me the following error:

Traceback (most recent call last): File "fclient.py", line 49, in client_socket.send(command) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 170, in _dummy raise error(EBADF, 'Bad file descriptor')

I'm totally lost. What is the best way to get a command line input in the client program and send it to the server and ask the server to validate the command line parameter? Can someone take a look and point me to the right direction? Your help is greatly appreciated.

Client.py

import socket   #for sockets
import sys      #for exit

command = ' '
socksize = 1024

#return a socket descriptor which can be used in other socket related functions
#properties: address family: AF_INET (IP v4)
#properties: type: SOCK_STREAM (connection oriented TCP protocol)

try:
    #create an AF_INET, STREAM socket (TCP)
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, msg:               #error handling
    print 'Failed to create socket. Error code: ' + str(msg[0]) + ', Error message: ' + msg[1]
    sys.exit();

print 'Socket Created'

#Get the IP address of the remote host/url
#connect to IP on a certain 'port' using the connect
#host = 'flip3.engr.oregonstate.edu'
#port = 30021
#host = 'www.google.com'
#port = 80
host = ''       #symbolic name meaning the local host
port = 8888     #arbitrary non-privileged port

try:
    remote_ip = socket.gethostbyname(host)
except socket.gaierror:
    #could not resolve
    print 'Hostname could not be resolved. Existing'
    sys.exit()
print 'IP address of ' + host + ' is ' + remote_ip

#Connect to remote server
client_socket.connect((remote_ip, port))
print 'Socket Connected to ' + host + ' on ip ' + remote_ip


#Send some data to remote server
while True:
    print 'Enter a command: list or get <filename>'
    command = raw_input()
    if command.strip() == 'quit':
        break
    client_socket.send(command)

    data = client_socket.recv(socksize)
    print data

#Close the socket
client_socket.close()

Server.py

import socket
import sys
from thread import *

#HOST = 'flip3.engr.oregonstate.edu' #symbolic name meaning all available interfaces
#PORT = 30021
HOST = ''
PORT = 8888

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created'

try:
    server_socket.bind((HOST, PORT))    #bind to a address(and port)
except socket.error, msg:
    print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
    sys.exit()

print 'Socket bind complete'

#put the socket in listening mode
server_socket.listen(10)     #maximum 10 connections
print 'TCP Server Waiting for client on port 30021'

#wait to accept a connection - blocking call
client, addr = server_socket.accept()
#display client information
print 'Connected with ' + addr[0] + ':' + str(addr[1])

#keep talking with the client
while 1:
    #Receiving from client
    data = client.recv(1024)

    if (data == 'list' or data == 'get'):
        reply = 'receive: ' + data
        client.send(reply)
        break;
    else:
        reply = 'wrong command'
        client.send(reply)

client.close()

2 Answers 2

3

The first problem is that you close your client socket inside your loop, closing it after receiving the reply to the first command. Move closing the socket out of the loop instead and introduce an exit condition to exit the loop:

#Connect to remote server
client_socket.connect((remote_ip, port))

print 'Socket Connected to ' + host + ' on ip ' + remote_ip

#Send some data to remote server
while True:
    print 'Enter a command: list or get <filename>'
    command = raw_input()
    if command.strip() == 'quit':
        break
    client_socket.send(command)

    data = client_socket.recv(socksize)
    print data

# Close the socket
client_socket.close()

You're doing something similar on the server side: You try to reopen the listening socket every iteration. Move this part out of the loop as well:

#wait to accept a connection - blocking call
client, addr = server_socket.accept()

#display client information
print 'Connected with ' + addr[0] + ':' + str(addr[1])

The reason your command parsing doesn't work is because of this statement:

if (data == 'list' or 'get'):

What you meant to write here is

if (data == 'list' or data == 'get'):

The first expression will evaluate like this:

  • Is data == 'list'?
  • If yes, that sub-expression evaluates to True and is therefore what a or b will return.
  • If not, the second operand to or is chosen, which is the string 'get'.
  • The result of that or expression will now be implicitely cast to boolean by the if statement:
  • Case 1: True is already True
  • Case 2: A non-empty string cast to boolean evaluates to True as well

So your if statement will always evaluate to True, that's why your command parsing didn't work.

To write

if (data == 'list' or data == 'get'):

in a nicer form, I would suggest to use

if (data.strip() in ('list'  'get')):

Lastly, you should wrap your socket code in a try..finally to make sure the sockets are always closed even if exceptions like a KeyboardInterrupt happen:

try:
    #keep talking with the client
    while 1:
        #Receiving from client
        data = client.recv(1024)

        if (data.strip() in ('list'  'get')):
            reply = 'receive: ' + data
            client.send(reply)
        else:
            reply = 'wrong command'
            client.send(reply)
except KeyboardInterrupt:
    print "Exiting gracefully."
finally:
    server_socket.close()

(The finally clause gets executed under all circumstances - whether handled or undhandled exceptions happened, or not)

Sign up to request clarification or add additional context in comments.

3 Comments

THANK U SOOO MUCH for the tips! It works now. =D Really appreciate it. Do you mind to answer one more question? If the user provides me a filename, e.g., get abc.txt. How can I read the text file name, search it within my directory and display the content of the text file? What topics should I look into (tutorial, example)?
You're welcome. Regarding your second question, look into str.split() to split 'get abc.txt' into ['get', 'abc.txt'], the functions in the os.path module to build paths (os.path.join), make your path absolute (os.path.abspath) and checking for existence of a file (os.path.isfile). Look at open() to open the file. If you need help putting those together, feel free to ask a new question.
U r awesome!!! =D Thanks again for your quick reply. I'll google the ones you told me.
0

One problem is that you close client_socket in your while loop. After that, client_socket.send() will not work anymore. There are at least two ways to fix this:

  1. Move client_socket.connect() into your while loop also.
  2. Get rid of client_socket.close(), and move server_socket.accept() above the while loop in Server.py.

There are more sophisticated options involving select() or other methods, but one of the two items above should get you by for now.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.