Need help on Socket Programming in Python (beginner)
Question: 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()
    


Answer: 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`](http://docs.python.org/2/tutorial/errors.html#defining-clean-
up-actions) clause gets executed under all circumstances - whether handled or
undhandled exceptions happened, or not)

