【问题标题】:Need help on Socket Programming in Python (beginner)在 Python 中的 Socket 编程需要帮助(初学者)
【发布时间】:2013-11-13 17:53:17
【问题描述】:

我正在学习套接字编程和 python。我需要创建一个将命令发送到服务器(list 或 get)的客户端。然后服务器验证该命令。我的客户端程序可以显示 "list" 或 "get" ,但是当我输入其他内容时它不会显示错误消息。
此外,它只能工作一次;当我在收到服务器的回复后输入不同的命令时,它给了我以下错误:

Traceback(最近一次调用最后一次): 文件“fclient.py”,第 49 行,在 client_socket.send(命令) _dummy 中的文件“/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py”,第 170 行 引发错误(EBADF,'错误的文件描述符')

我完全迷路了。在客户端程序中获取命令行输入并将其发送到服务器并要求服务器验证命令行参数的最佳方法是什么?有人可以看看并指出我正确的方向吗?非常感谢您的帮助。

客户端.py

import socket   #for sockets
import sys      #for exit

command = ' '
socksize = 1024

#return a socket descriptor which can be used in other socket related functions
#properties: address family: AF_INET (IP v4)
#properties: type: SOCK_STREAM (connection oriented TCP protocol)

try:
    #create an AF_INET, STREAM socket (TCP)
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, msg:               #error handling
    print 'Failed to create socket. Error code: ' + str(msg[0]) + ', Error message: ' + msg[1]
    sys.exit();

print 'Socket Created'

#Get the IP address of the remote host/url
#connect to IP on a certain 'port' using the connect
#host = 'flip3.engr.oregonstate.edu'
#port = 30021
#host = 'www.google.com'
#port = 80
host = ''       #symbolic name meaning the local host
port = 8888     #arbitrary non-privileged port

try:
    remote_ip = socket.gethostbyname(host)
except socket.gaierror:
    #could not resolve
    print 'Hostname could not be resolved. Existing'
    sys.exit()
print 'IP address of ' + host + ' is ' + remote_ip

#Connect to remote server
client_socket.connect((remote_ip, port))
print 'Socket Connected to ' + host + ' on ip ' + remote_ip


#Send some data to remote server
while True:
    print 'Enter a command: list or get <filename>'
    command = raw_input()
    if command.strip() == 'quit':
        break
    client_socket.send(command)

    data = client_socket.recv(socksize)
    print data

#Close the socket
client_socket.close()

服务器.py

import socket
import sys
from thread import *

#HOST = 'flip3.engr.oregonstate.edu' #symbolic name meaning all available interfaces
#PORT = 30021
HOST = ''
PORT = 8888

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created'

try:
    server_socket.bind((HOST, PORT))    #bind to a address(and port)
except socket.error, msg:
    print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
    sys.exit()

print 'Socket bind complete'

#put the socket in listening mode
server_socket.listen(10)     #maximum 10 connections
print 'TCP Server Waiting for client on port 30021'

#wait to accept a connection - blocking call
client, addr = server_socket.accept()
#display client information
print 'Connected with ' + addr[0] + ':' + str(addr[1])

#keep talking with the client
while 1:
    #Receiving from client
    data = client.recv(1024)

    if (data == 'list' or data == 'get'):
        reply = 'receive: ' + data
        client.send(reply)
        break;
    else:
        reply = 'wrong command'
        client.send(reply)

client.close()

【问题讨论】:

    标签: python sockets command-line-arguments


    【解决方案1】:

    第一个问题是你关闭了你的客户端套接字inside你的循环,在收到第一个命令的回复后关闭它。将关闭套接字移出循环并引入退出条件以退出循环:

    #Connect to remote server
    client_socket.connect((remote_ip, port))
    
    print 'Socket Connected to ' + host + ' on ip ' + remote_ip
    
    #Send some data to remote server
    while True:
        print 'Enter a command: list or get <filename>'
        command = raw_input()
        if command.strip() == 'quit':
            break
        client_socket.send(command)
    
        data = client_socket.recv(socksize)
        print data
    
    # Close the socket
    client_socket.close()
    

    您在服务器端做了类似的事情:您尝试在每次迭代时重新打开侦听套接字。也将这部分移出循环:

    #wait to accept a connection - blocking call
    client, addr = server_socket.accept()
    
    #display client information
    print 'Connected with ' + addr[0] + ':' + str(addr[1])
    

    你的命令解析不起作用的原因是因为这个语句:

    if (data == 'list' or 'get'):
    

    你的意思是写在这里

    if (data == 'list' or data == 'get'):
    

    第一个表达式的计算结果如下:

    • 是data == 'list'吗?
    • 如果是,则该子表达式的计算结果为 True,因此是 a or b 将返回的内容。
    • 如果不是,则选择or 的第二个操作数,即字符串'get'。
    • or 表达式的结果现在将通过 if 语句隐式转换为布尔值:
    • 案例1:True已经是True
    • 案例 2:转换为布尔值的非空字符串的计算结果也为 True

    所以您的if 语句将始终评估为True,这就是您的命令解析不起作用的原因。

    写作

    if (data == 'list' or data == 'get'):
    

    以更好的形式,我建议使用

    if (data.strip() in ('list'  'get')):
    

    最后,您应该将套接字代码包装在 try..finally 中,以确保即使发生 KeyboardInterrupt 之类的异常,套接字也始终处于关闭状态:

    try:
        #keep talking with the client
        while 1:
            #Receiving from client
            data = client.recv(1024)
    
            if (data.strip() in ('list'  'get')):
                reply = 'receive: ' + data
                client.send(reply)
            else:
                reply = 'wrong command'
                client.send(reply)
    except KeyboardInterrupt:
        print "Exiting gracefully."
    finally:
        server_socket.close()
    

    (finally 子句在所有情况下都会执行 - 无论是否发生已处理或未处理的异常)

    【讨论】:

    • 非常感谢您的提示!现在可以了。 =D 真的很感激。你介意再回答一个问题吗?如果用户提供给我一个文件名,例如,获取 abc.txt。如何读取文本文件名、在我的目录中搜索并显示文本文件的内容?我应该研究哪些主题(教程、示例)?
    • 不客气。关于你的第二个问题,查看str.split() 将'get abc.txt' 拆分为['get', 'abc.txt'],os.path 模块中的函数用于构建路径(os.path.join),使你的路径绝对(os.path.abspath)并检查是否存在文件 (os.path.isfile)。查看open() 打开文件。如果您需要帮助将它们组合在一起,请随时提出新问题。
    • 你真棒!!! =D 再次感谢您的快速回复。我会用谷歌搜索你告诉我的那些。
    【解决方案2】:

    一个问题是您在 while 循环中关闭了 client_socket。之后,client_socket.send() 将不再起作用。至少有两种方法可以解决这个问题:

    1. 将 client_socket.connect() 也移动到您的 while 循环中。
    2. 去掉client_socket.close(),将server_socket.accept()移到Server.py中while循环的上方。

    还有更复杂的选项涉及select() 或其他方法,但上述两项中的一项现在应该可以帮助您。

    【讨论】:

      猜你喜欢
      • 2020-08-08
      • 1970-01-01
      • 2021-04-11
      • 2022-01-17
      • 1970-01-01
      • 1970-01-01
      • 2018-01-18
      • 1970-01-01
      • 2021-01-09
      相关资源
      最近更新 更多