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


所以我只是进入python并尝试了一些东西。首先,我正在创建一个服务器,它可以执行简单的操作,例如“GET”的存储文本,“存储”旧文本上的新文本,以及“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()

6413
2017-09-24 01:55


起源

它在引发压痕错误时给出的错误应该给出它所在或接近的行号。
谢谢!我更新了描述的行(data = conn.recv(1024))。 - Katie Jurek
这是在你编辑之前,对吗?现在,如果您运行此代码,它应该没问题。 - justhalf
不,遗憾的是data = conn.recv(1024)仍然存在缩进错误。 :( - Katie Jurek
您确定您的代码与我们在此处看到的相同吗?我在我的机器上运行它并且工作正常。 - justhalf


答案:


我发现你对Python很陌生。您可以尝试查找一些代码示例,以及您 应该 还学习如何解释错误消息。错误消息将为您提供应该查看的行号。您应该考虑该行或上一行,因为错误可能是由先前的错误引起的。

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

关于你真正的问题,首先是概念。

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

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

对于初学者,您不需要包含 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

客户端控制台上的示例运行(首先运行服务器,然后运行客户端):

输入您的命令:STORE这是一个文本
好
输入您的命令:GET
这是一篇文章
输入您的命令:TRANSLATE
这是一篇文章
输入您的命令:GET
这是一篇文章
输入您的命令:QUIT

我希望你能从那里继续。

另一个重要的一点是,你正在使用TCP(socket.SOCK_STREAM),所以你可以在接受它后实际保留连接 s.accept(),你应该只在完成该连接上的任务时关闭它(接受新连接有其开销)。您当前的代码只能处理单个客户端。但是,我认为首先,这已经足够了。在您对此有信心之后,您可以尝试使用以处理更多客户端 穿线


13
2017-09-24 02:31



十分感谢你的帮助!我确实有一个问题:接受一个命令后,连接关闭。我该如何保持开放状态?对于大写,要添加一点,我将如何转换客户端所说的任何内容(直到他们在一行上键入一个'。')为大写(如果他们的文本那么长,包括换行符)? - Katie Jurek
你确定在接受一个命令后连接关闭了吗?你的意思是在服务器完成一个客户端之后?我提供的样本运行是单次运行。对于您的其他问题,应该在客户端完成。看我的编辑。请注意,最大长度为1024个字符,因为在此版本中我们只读取1024个字节( recv(1024) 在服务器和客户端)一次。如果你想阅读更多,你需要一个循环。 - justhalf
是的,它说这是因为这个“data = conn.recv(1024)”行。它是在一个命令之后,而不是在完整客户端之后。我现在只发送GET,STORE,TRANSLATE或EXIT。 - Katie Jurek
嗯,很奇怪,在我的机器上它一直在运行,直到客户输入'QUIT'。服务器或客户端中是否有错误消息? - justhalf
在服务器中,它表示连接已被我的主机中的软件中止。 - Katie Jurek