Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python socket server/client programming

So I am just getting into python and trying out some stuff. To start, I am making a server that does simple stuff like "GET"s stored text, "STORE"s new text over the old stored text, and "TRANSLATE"s lowercase text into uppercase. But I have a few questions. Here is my code so far:

import socket

HOST = ''   # Symbolic name meaning the local host
PORT = 24069    # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created'
try:
    s.bind((HOST, PORT))
except socket.error , msg:
    print 'Bind failed. Error code: ' + str(msg[0]) + 'Error message: ' + msg[1]
    sys.exit()
print 'Socket bind complete'
s.listen(1)
print 'Socket now listening'
while 1:
    conn, addr = s.accept()
    print 'Connected with ' + addr[0] + ':' + str(addr[1])
    data = conn.recv(1024)
    reply = 'OK...' + data
    if not data: break
    conn.send(data)
conn.close()
s.close()

To start changing text from a client into uppercase, from my other programming knowledge, I assume I'd store the client's text in a variable and then run a function on it to change it to uppercase. Is there such a function in python? Could someone please give me a snippet of how this would look?

And lastly, how would I do something like a GET or STORE in python? My best guess would be:

data = conn.recv(1024)
if data == GET: print text
if data == STORE: text = data #Not sure how to reference the text that the client has entered

Thank you so much for any help! :)

Note to self:

import socket

HOST = ''   # Symbolic name meaning the local host
PORT = 24069    # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created'
try:
    s.bind((HOST, PORT))
except socket.error , msg:
    print 'Bind failed. Error code: ' + str(msg[0]) + 'Error message: ' + msg[1]
    sys.exit()
print 'Socket bind complete'
s.listen(1)
print 'Socket now listening'

# Accept the connection
(conn, addr) = s.accept()
print 'Server: got connection from client ' + addr[0] + ':' + str(addr[1])
storedText = 'Hiya!'
while 1:
    data = conn.recv(1024)
    tokens = data.split(' ', 1)
    command = tokens[0]
    if command == 'GET':
        print addr[0] + ':' + str(addr[1]) + ' sends GET'
        reply = storedText
    elif command == 'STORE':
        print addr[0] + ':' + str(addr[1]) + ' sends STORE'  
        storedText = tokens[0]
        reply = '200 OK\n' + storedText
    elif command == 'TRANSLATE':
        print addr[0] + ':' + str(addr[1]) + ' sends TRANSLATE'
        storedText = storedText.upper()
        reply = storedText
    elif command == 'EXIT':
        print addr[0] + ':' + str(addr[1]) + ' sends EXIT'
        conn.send('200 OK')
        break
    else:
        reply = '400 Command not valid.'

    # Send reply
    conn.send(reply)
conn.close()
s.close()
like image 335
Programmer Avatar asked Sep 24 '13 01:09

Programmer


1 Answers

I see that you're quite new to Python. You can try to find some code example, and you should also learn how to interpret the error message. The error message will give you the line number where you should look at. You should consider that line or previous line, as the error may be caused by previous mistakes.

Anyway, after your edits, do you still have indentation error?

On your real question, first, the concept.

To run client/server, you'll need two scripts: one as the client and one as the server.

On the server, the script will just need to bind to a socket and listen to that connection, receive data, process the data and then return the result. This is what you've done correctly, except that you just need to process the data before sending response.

For starter, you don't need to include the accept in the while loop, just accept one connection, then stay with it until client closes.

So you might do something like this in the server:

# Accept the connection once (for starter)
(conn, addr) = s.accept()
print 'Connected with ' + addr[0] + ':' + str(addr[1])
stored_data = ''
while True:
    # RECEIVE DATA
    data = conn.recv(1024)

    # PROCESS DATA
    tokens = data.split(' ',1)            # Split by space at most once
    command = tokens[0]                   # The first token is the command
    if command=='GET':                    # The client requests the data
        reply = stored_data               # Return the stored data
    elif command=='STORE':                # The client want to store data
        stored_data = tokens[1]           # Get the data as second token, save it
        reply = 'OK'                      # Acknowledge that we have stored the data
    elif command=='TRANSLATE':            # Client wants to translate
        stored_data = stored_data.upper() # Convert to upper case
        reply = stored_data               # Reply with the converted data
    elif command=='QUIT':                 # Client is done
        conn.send('Quit')                 # Acknowledge
        break                             # Quit the loop
    else:
        reply = 'Unknown command'

    # SEND REPLY
    conn.send(reply)
conn.close() # When we are out of the loop, we're done, close

and in the client:

import socket

HOST = ''   # Symbolic name meaning the local host
PORT = 24069    # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST,PORT))
while True:
    command = raw_input('Enter your command: ')
    if command.split(' ',1)[0]=='STORE':
        while True:
            additional_text = raw_input()
            command = command+'\n'+additional_text
            if additional_text=='.':
                break
    s.send(command)
    reply = s.recv(1024)
    if reply=='Quit':
        break
    print reply

Sample run (first run the server, then run the client) on client console:

Enter your command: STORE this is a text
OK
Enter your command: GET
this is a text
Enter your command: TRANSLATE
THIS IS A TEXT
Enter your command: GET
THIS IS A TEXT
Enter your command: QUIT

I hope you can continue from there.

Another important point is that, you're using TCP (socket.SOCK_STREAM), so you can actually retain the connection after accepting it with s.accept(), and you should only close it when you have accomplished the task on that connection (accepting new connection has its overhead). Your current code will only be able to handle single client. But, I think for starter, this is good enough. After you've confident with this, you can try to handle more clients by using threading.

like image 104
justhalf Avatar answered Oct 22 '22 22:10

justhalf