web-dev-qa-db-ja.com

Pythonソケットサーバー/クライアントプログラミング

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にそのような関数はありますか?誰かが私にこれがどのように見えるかのスニペットを教えてもらえますか?

そして最後に、PythonでGETまたはSTOREのようなことをするにはどうすればよいですか?私の最も良い推測は:

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()
11
Katie Jurek

あなたはPythonにかなり慣れているようです。あなたはいくつかのコード例を見つけることを試みることができます、そしてあなたshouldもエラーメッセージを解釈する方法を学びます。エラーメッセージには、確認すべき行番号が表示されます。エラーは以前のミスが原因で発生する可能性があるため、その行または前の行を考慮する必要があります。

とにかく、編集後もインデントエラーはありますか?

あなたの本当の質問について、最初に、コンセプト。

クライアント/サーバーを実行するには、2つのスクリプトが必要です。1つはクライアントとして、もう1つはサーバーとしてです。

サーバーでは、スクリプトはソケットにバインドしてその接続をリッスンし、データを受信し、データを処理して、結果を返すだけです。これは、応答を送信する前にデータを処理する必要があることを除いて、あなたが正しく行ったことです。

まず、whileループにacceptを含める必要はありません。1つの接続を受け入れ、クライアントが閉じるまでそのままにしておきます。

したがって、サーバーで次のようなことを行う可能性があります。

_# 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
_

クライアントコンソールでのサンプル実行(最初にサーバーを実行し、次にクライアントを実行):

コマンドを入力してください:STOREこれはテキストです
 OK 
コマンドを入力してください:GET 
これはテキストです
コマンドを入力してください:TRANSLATE 
 THIS IS A TEXT 
コマンドを入力:GET 
 THIS IS A TEXT 
コマンドを入力してください:QUIT 

よろしくお願いします。

もう1つの重要な点は、TCP(_socket.SOCK_STREAM_)を使用しているため、s.accept()で接続を受け入れた後、実際に接続を保持できることです。その接続でタスクを完了したときにのみ閉じてください(新しい接続を受け入れるとオーバーヘッドが発生します)。現在のコードは1つのクライアントしか処理できません。しかし、最初はこれで十分だと思います。これにより、 threading を使用して、より多くのクライアントを処理することができます。

13
justhalf