Python套接字服务器/客户端编程

11

所以我刚开始学习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()

当出现缩进错误时,它所报告的错误应该给出其所在或附近的行号。 - user764357
谢谢!我更新了描述,说明它是哪一行(data = conn.recv(1024))。 - Programmer
1
这是在你编辑之前的代码,对吧?现在如果你运行这段代码应该没问题了。 - justhalf
不幸的是,在data = conn.recv(1024)处仍然存在缩进错误。 :( - Programmer
你确定你的代码和我们在这里看到的一样吗?我在我的机器上运行它,它可以正常工作。 - justhalf
显然,某些地方存在额外的空格?感谢您帮助解决第一部分问题! :) - Programmer
1个回答

13

我看到你对Python还很新。你可以尝试找一些代码示例,并且应该学习如何解释错误信息。错误信息会给出应该查看的行号。你应该考虑该行或前一行,因为错误可能是由之前的错误引起的。

无论如何,在你编辑后,你还有缩进错误吗?

关于你真正的问题,首先,介绍一下概念。

要运行客户端/服务器,你需要两个脚本:一个作为客户端,一个作为服务器。

在服务器上,脚本只需要绑定到套接字并监听该连接,接收数据,处理数据,然后返回结果。这是你已经正确执行的操作,只是需要在发送响应之前处理数据。

对于初始者来说,你不需要在while循环中包含 accept,只需接受一个连接,然后保持与它连接直到客户端关闭。

所以你可能会在服务器上做出这样的改变:

# 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 this is a text
OK
输入您的命令:GET
this is a text
输入您的命令:TRANSLATE
THIS IS A TEXT
输入您的命令:GET
THIS IS A TEXT
输入您的命令:QUIT

希望你能从这里继续。

另一个重要的点是,你正在使用 TCP (socket.SOCK_STREAM),所以你实际上可以在接受连接后保留连接,并且只有在完成该连接上的任务后才关闭它(接受新连接会有开销)。但是,你当前的代码只能处理单个客户端。但是,我认为对于初学者来说,这已经足够了。在你对此感到自信之后,你可以尝试通过使用线程来处理更多的客户端。


你确定在接受一个命令后连接会关闭吗?你是指服务器完成一个客户端后会关闭吗?我提供的样例运行只有一次。关于你的额外问题,应该在客户端完成。请查看我的编辑。请注意,最大长度为1024个字符,因为在此版本中我们只读取1024字节(服务器和客户端中的recv(1024))一次。如果你想读取更多,就需要循环了。 - justhalf
是的,这是因为这行代码 "data = conn.recv(1024)"。 它是在一个命令后面,而不是整个客户端之后。 我现在只发送GET、STORE、TRANSLATE或EXIT。 - Programmer
嗯,奇怪,在我的机器上它一直运行到客户端输入“QUIT”。服务器或客户端有错误消息吗? - justhalf
服务器显示连接被我的主机软件中止。 - Programmer
无论如何,非常感谢您的帮助!除了每个命令后关闭它之外,我还得到了其他东西。再次感谢,justhalf! :D - Programmer
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接