Python3.6,OSError:[Errno 57]套接字未连接

时间:2018-10-13 02:36:36

标签: python networking

我试图在python中编写类似UDP的协议,其中包含诸如three_handshake之类的一些详细信息,但是我无法运行server.py,因为它这样告诉我:

Traceback (most recent call last):
File "/Users/suiyoucheng/PycharmProjects/9331 ASS/receiver.py", line 
38, in <module>
BYTE_fh, senderAddress = receiverSocket.recvfrom(1024)
OSError: [Errno 57] Socket is not connected

和我的server.py代码如下所示:

try:
    receiverSocket = socket(AF_INET, SOCK_STREAM)
except:
    print("Failed to create receiver socket.")
    sys.exit()


receivePort = 2000
try:
    receiverSocket.bind(('', receivePort))
except:
    print("Bind failed.")
    sys.exit()

#                           First Hand Shake                              #

receiver_ISN = 0
receiver_ITIME = time.time()


BYTE_fh, senderAddress = receiverSocket.recvfrom(1024) #**where I got wrong**#
first_hand = pickle.loads(BYTE_fh)

你们能告诉我如何解决吗?非常感谢。

2 个答案:

答案 0 :(得分:0)

您需要开始侦听连接,然后才能从套接字读取数据。 请在bind()之后添加receiverSocket.listen()和receiverSocket.accept()。 除了使用原始套接字,还可以使用socketserver

创建服务器所需的总体步骤(无异常处理):

srvsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = (socket.gethostname(), 25000)
srvsock.bind(server_address)
srvsock.listen(5)
connection, client_address = srvsock.accept()
data = connection.recv(1024)

答案 1 :(得分:0)

您还将需要一个客户端套接字来测试服务器。下面是可以使用的更完整的ClientSocket类。您可以一次使用cnsdrcv()函数进行收发交互。在服务器端也可以使用相同的类与客户端连接进行交互-

connection, client_address = serverSocket.accept()
clntCon = ClientSocket()
clntCon.useSocket(connection).connect()
dataBytes = clntCon.rcvAllSent()
# Process all the "dataBytes" and then respond back
clntCon.send(responseBytes)
clntCon.close()

#----------------------------------------------------------------------------------------------------------

def cnsdrcv(host, port, data, timeout=1):
  # data - bytes()
  # returns data chunks as list of bytes()

  # Create a TCP/IP socket
  sock = ClientSocket()
  sock.useHost(host, port, timeout)

  try:
    sock.connect()

    # Send data
    sock.send(data)

    return sock.rcvUntilTimeout()
  finally:
    sock.close()

下面的完整课程-

class ClientSocket:

  def __init__(self, name=None):
    logging.debug("ClientSocket [{}] : __init__()".format(name))
    self.Name = name
    self.sock = None
    self.server_address = None

  @property
  def Name(self):
    if self.__Name is None and self.server_address is not None:
      self.Name = str(self.server_address[1])

    return self.__Name

  @Name.setter
  def Name(self, name):
    self.__Name = name

  @Name.deleter
  def Name(self):
    del self.__Name


  def useSocket(self, sock, timeout=1):
    # Socket is assumed to be already connected
    logging.debug("ClientSocket [{}] : useSocket()".format(self.Name))

    if sock is None:
      raise ValueError("ClientSocket.useSocket() : sock arg cannot be None")

    if self.sock is None:
      self.server_address = sock.getpeername()
      self.sock = sock
      self.timeout = timeout
      self.sock.settimeout(self.timeout)
      return self
    else:
      raise AttributeError("ClientSocket.useSocket() : is already in use")


  def useHost(self, host, port, timeout=1):
    logging.debug("ClientSocket [{}] : useHost()".format(self.Name))

    if host == None or len(host) == 0:
      host = socket.gethostname()
    self.server_address = (host, port)
    self.timeout = timeout


  def connect(self):
    logging.debug("ClientSocket [{}] : connect()".format(self.Name))

    if self.sock is None:
    # Create a TCP/IP socket
      self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      logging.info('connecting to {} port {}'.format(*self.server_address))

      # Connect the socket to the port where the server is listening
      self.sock.connect(self.server_address)
      self.sock.settimeout(self.timeout)
    else:
      self.isValid()


  def isValid(self):
    if not self.sock:
      return False

    try:
      if self.sock.fileno() == -1:
    except:
      return False

    try:
      self.sock.getsockname()
    except socket.error as e:
      if e.args[0] == errno.EBADF:
        # Socket is CLOSED
        pass
      return False

    try:
      self.sock.getpeername()
    except socket.error as e:
      if e.args[0] in [errno.EBADF, errno.ENOTCONN]:
        # Socket is CLOSED
        pass
      return False

    return True


  def send(self, data):
    # data must be a bytes or Data object
    logging.debug("ClientSocket [{}] : send()".format(self.Name))

    logging.debug('sending {!r}'.format(data))

    if not self.isValid() :
      logging.error("Client Socket in BAD state, cannot send")

    if isinstance(data, str):
      data = data.encode()

    try:
      # Send data
      self.sock.sendall(data)
    except:
      raise

  def rcvOnce(self, rcvSz, timeout=5):
    # receive at least one byte, waiting for timeout secs
    # returns bytes containing max rcvSz bytes
    logging.debug("ClientSocket [{}] : rcvOnce()".format(self.Name))

    if not self.isValid() :
      logging.error("Client Socket in BAD state, cannot receive")
      return None

    strtTime = time.time()
    while True:
      try:
        chunk = self.sock.recv(rcvSz)
        break
      except socket.timeout:
        logging.debug("Socket recv timedout, re-trying")
        if time.time() - strtTime >= timeout:
          raise
        continue
      except:
        logging.exception("Receive exception")
        raise

    if chunk is None or len(chunk) == 0:
      logging.debug("Received len [0]")
    else:
      logging.debug("Received len [{}]".format(len(chunk)))

    return chunk

  def rcvAllSent(self, timeout=5):
    # Returns a Data object
    logging.debug("ClientSocket [{}] : rcvAllSent()".format(self.Name))

    if not self.isValid() :
      logging.error("Client Socket in BAD state, cannot receive")
      return None

    chunks = []
    strtTime = time.time()
    while True:
      try:
        chunk = self.sock.recv(1024)
      except socket.timeout as e:
        logging.debug("Read Timeout occurred [{}]".format(e))
        if time.time() - strtTime >= timeout:
          raise
        continue
      except socket.error as e:
        logging.error("Some Socket error occurred [{}]".format(e))
        break
      else:
        if len(chunk) == 0:
          logging.info("Received empty chunk, could be due to socket close()")
          break
        else:
          chunks.append(chunk)
          if len(chunk) < 1024:
            break
          else:
            continue

    return b''.join(chunks)

  def rcvUntilTimeout(self, rcvSz=2048):
    # returns a list of received bytes() objects
    logging.debug("ClientSocket [{}] : rcvUntilTimeout()".format(self.Name))

    if not self.isValid() :
      logging.error("Client Socket in BAD state, cannot receive")
      return None

    chunks  = []
    tchunkb = []

    chunk = self.rcvOnce(rcvSz)
    if chunk is None or len(chunk) == 0:
      # Socket closed by the remote
      return None
    else:
      chunks.append(chunk)

    while True:
      try:
        chunkb = self.sock.recv(rcvSz)
      except socket.timeout as e:
        logging.debug("Socket recv timedout")
        break
      except socket.error:
        logging.exception("Socket recv error")
        raise
      except:
        logging.exception("Unknown Exception while recv")
        raise
      else:
        if len(chunkb) == 0:
          logging.info("Received empty chunk indicating remote end closed the socket")
          break
        else:
          logging.debug("Received len [{}]".format(len(chunkb)))
          tchunkb.append(chunkb)
          if len(chunkb) < rcvSz:
            chunks.append(b''.join(tchunkb))
            tchunkb = []
          else:
            continue

    return chunks

  def close(self):
    logging.debug("ClientSocket [{}] : close()".format(self.Name))

    if self.isValid():
      self.sock.shutdown(socket.SHUT_RDWR)
      self.sock.close()