Python 3:TCP客户端/服务器断开管道错误

Python 3:TCP客户端/服务器断开管道错误,python,tcp,python-3.x,client-server,broken-pipe,Python,Tcp,Python 3.x,Client Server,Broken Pipe,我正在编写一个TCP客户机/服务器,在代码的后半部分我遇到了这个错误。由于对Python和socket编程的理解有限,我无法找出原因,因此无法解决问题。我将不得不包括所有的代码,因为可能会有一些冲突导致这个问题,我不知道,抱歉的长文章 我已经标记了我在下面遇到的问题,到目前为止一切都很好 服务器代码: import os from socket import * import urllib import time HOST = '' #We are the host PORT = 29876

我正在编写一个TCP客户机/服务器,在代码的后半部分我遇到了这个错误。由于对Python和socket编程的理解有限,我无法找出原因,因此无法解决问题。我将不得不包括所有的代码,因为可能会有一些冲突导致这个问题,我不知道,抱歉的长文章

我已经标记了我在下面遇到的问题,到目前为止一切都很好

服务器代码:

import os
from socket import *
import urllib
import time

HOST = '' #We are the host
PORT = 29876
PORT2 = 29877
ADDR = (HOST, PORT)
ADDR2 = (HOST, PORT2)

BUFFSIZE = 4096


serv =  socket( AF_INET,SOCK_STREAM)
serv.bind(ADDR,)
serv.listen(5)
print ('listening... \n')


conn,addr = serv.accept()
print (conn,addr)
print ('...connected \n')

with open(os.path.expanduser("~/.ssh/id_rsa.pub")) as f:
    key = f.read()
    conn.sendall(key)
print("Key Sent... \n")


data = conn.recv(BUFFSIZE)
with open('ip.txt', 'w') as myfile:
    myfile.write(str(data))

with open("ip.txt", "r") as myfile:
    ip=myfile.read().replace('\n','')
print("The client IP is: " + ip + "\n")

conn.close()


ver = socket(AF_INET,SOCK_STREAM)
ver.bind(ADDR2,)
ver.listen(5)
print('listening...\n')

build,addr = ver.accept()
print (build,addr)
print('...connected\n')

#Get Version
version = urllib.urlopen("http://p.b.r.com/pa/b/latest.txt")
print(version.read())

#IT IS SENDING THIS LAST PIECE OF DATA THAT CAUSES THE BROKEN PIPE ERROR
version = str(version.read())
ver.send(version)
客户端代码:

from socket import *
from winreg import *
import os
import socket
import platform
import string
import time

#Detect OS
os = platform.system()
print("Your system is running "+ os)

#Set Host address and port
HOST = 'xxx.xxx.xxx.xxx'
PORT = 29876
PORT2 = 29877
ADDR = (HOST,PORT)
ADDR2 = (HOST, PORT2)
BUFFSIZE = 4096


cli = socket.socket( AF_INET, SOCK_STREAM)
cli.connect(ADDR,)


#Get and send IP
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("gmail.com",80))
ip = ((s.getsockname()[0]))
ip = ip.encode('utf-8')
cli.send(ip)
print("IP Sent... \n")

#Set received key to write to known hosts
data = cli.recv(BUFFSIZE)
with open('C:\cygwin\home\scollins\.ssh\known_hosts', 'w') as myfile:
    myfile.write(str(data,'utf-8'))
print("Key Saved To Known Hosts")

#Close opened sockets
s.close()
cli.close()


ver = socket.socket( AF_INET, SOCK_STREAM)
ver.connect(ADDR2,)

#Get version/build number
if os == "Windows":
    #Connect to the registry
    regKey = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
    subKey = OpenKey(regKey, r"SOFTWARE\R\R Client")
    buildno = QueryValueEx(subKey, "Version")
else:
    if os == "Darwin":
        buildno = open("\Library\R\buildno")
    else:
        if os == "Linux":
           buildno = open("\r\buildno")


print("You are running software build number " + str(buildno))


#Receive and write server software version to file. Read file and compare build number
data = ver.recv(BUFFSIZE)

#THIS NEXT PRINT COMMAND RETURNS NOTHING WHICH I ASSUME IS DUE TO NOTHING BEING RECEIVED DUE TO THE BROKEN PIPE
print(str(data))
with open('version.text', 'w') as myfile:
    myfile.write(str(data,'utf-8'))

with open('version.txt', 'r') as myfile:
    version = myfile.read()
print("The software on the server is version: " + version)

if buildno in version == True:
    print("Your sofware version is up to date")
else:
    print("Your software is out of date. Updating your software.")
    os.system('')

ver.close()

感谢您提供的任何帮助。

好吧,我没有在这里安装python3,但仅从代码来看,您似乎正在尝试使用服务器部件中的服务器套接字发送一些内容

您通过以下方式呼叫accept:

build,addr = ver.accept()
然后尝试在版本上发送,而不是生成:

ver.send(version)
通常它是这样工作的: 在服务器端,您有一个“服务器”套接字,您将其调用bind On,然后接受,等待传入的连接。每次客户端连接时,accept都会生成一个套接字来与该特定客户端通信(“客户端”套接字)。如果所有的通信都是通过服务器套接字进行的,那么您怎么可能有多个客户端,并且知道您正在与哪个客户端“交谈”

代码中的第二个错误是,调用了version.read()来打印值,然后再次发送。read()会“消耗”数据,因此第二个read()会给出一个空结果


此外,还应该在循环中调用send(),检查其返回值,以确保所有数据都已实际发送。部分发送可能会发生。

感谢您的快速回复,您的回答是100%正确的。然而,我遇到了另一个问题。未发送版本的值,而是接收到一个空字节标记(b“”)。可能值得注意的是,在将version转换为要发送的字符串之前,它是一个tuple.Mh,否,请再次查看文档:您也可以这样做:version=urllib.urlopen(“)print(version.read())version是一个文件描述符类型的对象,您可以在其上执行read()为了获取数据。你正在尝试将一个对象转换为一个没有字符串表示的字符串。此外,如果它解决了你的问题,请不要忘记接受并向上投票;)另外,时间怎么了。睡眠(120)?如果我有声誉,我会向上投票哈哈。我打印的原因(version.read())因为没有它,版本号就不会打印,相反,我会得到““。我其实是想取消睡眠命令。这只是因为我认为一个连接可能没有正确关闭,我认为超时时间可能长达2分钟,所以我希望等待可以解决我看到的问题。这就是我所说的version.read。稍后,您尝试发送str(version),但您应该发送任何版本。read()返回的!