Python сокет-сервер/клиентское программирование

Итак, я просто вхожу в питон и пробую кое-что. Для начала я создаю сервер, который делает простые вещи, такие как "GET" сохраненный текст, новый текст "STORE" поверх старого сохраненного текста и строчный текст "TRANSLATE" в верхнем регистре. Но у меня есть несколько вопросов. Вот мой код:

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()

Чтобы начать изменять текст с клиента в верхний регистр, из других моих знаний по программированию, я предполагаю, что я бы сохранил текст клиента в переменной, а затем запустил на нем функцию, чтобы изменить ее на верхний регистр. Есть ли такая функция в python? Может кто-нибудь, пожалуйста, дайте мне фрагмент того, как это будет выглядеть?

И, наконец, как бы я сделал что-то вроде GET или STORE в python? Мое лучшее предположение:

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

Большое вам спасибо за любую помощь!:)

Примечание для себя:

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()

Ответ 1

Я вижу, что вы совершенно новичок в Python. Вы можете попробовать найти пример кода, и вы должны также узнать, как интерпретировать сообщение об ошибке. Сообщение об ошибке даст вам номер строки, на которой вы должны посмотреть. Вы должны рассмотреть эту строку или предыдущую строку, так как ошибка может быть вызвана предыдущими ошибками.

В любом случае, после ваших изменений у вас все еще есть ошибка отступов?

На ваш реальный вопрос, во-первых, понятие.

Для запуска клиента/сервера вам понадобятся два сценария: один в качестве клиента и один как сервер.

На сервере script просто нужно будет привязать к сокету и прослушать это соединение, получить данные, обработать данные и затем вернуть результат. Это то, что вы сделали правильно, за исключением того, что вам просто нужно обработать данные перед отправкой ответа.

Для стартера вам не нужно включать accept в цикл while, просто примите одно соединение, а затем оставайтесь с ним, пока клиент не закроется.

Итак, вы можете сделать что-то подобное на сервере:

# 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

и в клиенте:

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

Пример запуска (сначала запустите сервер, а затем запустите клиент) на клиентской консоли:

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

Надеюсь, вы сможете продолжить оттуда.

Другим важным моментом является то, что вы используете TCP (socket.SOCK_STREAM), поэтому вы можете фактически сохранить соединение после принятия его с помощью s.accept(), и вы должны закрыть его, только когда вы выполнили задачу по этому соединению (принятие нового соединения имеет накладные расходы). Ваш текущий код сможет обрабатывать только одного клиента. Но, думаю, для стартера это достаточно хорошо. После того, как вы уверены в этом, вы можете попробовать обработать больше клиентов, используя threading.