【问题标题】:Python, client-server application, does not connectPython,客户端-服务器应用程序,不连接
【发布时间】:2017-11-06 19:02:17
【问题描述】:

由于某种原因,下一个基本程序仅从第二次开始将客户端连接到服务器。所以每次重新启动服务器后。有人可以解释这种行为的原因以及如何解决这个问题吗?也许是因为 asyncore 只在服务器端使用? (Windows 7、Python 3)提前致谢!

客户:

import socket
sock = socket.socket()
host = 'localhost'
port = 8081
tempr = port
sock.connect((host,port))

服务器:

import asyncore 
import socket 
import time

class EchoHandler(asyncore.dispatcher_with_send):

def handle_read(self):
  data = self.recv(1024)

class EchoServer(asyncore.dispatcher):
  def __init__(self, host, port):
  asyncore.dispatcher.__init__(self)
  self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
  self.set_reuse_addr()
  self.bind((host, port))
  self.listen(2)

  def handle_accept(self):
    pair = self.accept()
    if pair is not None:
      sock, addr = pair
      print ('Incoming connection from %s' % repr(addr))
      handler = EchoHandler(sock)

def main():
  host = 'localhost'
  port = 8081
  server = EchoServer(host, port)

  print ('Server %s running'% port)
  asyncore.loop()

if __name__ == '__main__': 
   main()

【问题讨论】:

  • 你得到什么错误?
  • 没有错误也没有异常,但是handle_accept()函数只是从第二次尝试连接客户端开始执行。
  • 我离开了文档,还不熟悉asyncore,但我猜你不应该在handle_except 中调用accept。服务器可能在接受连接后调用该函数,因此它是多余的。
  • 这很奇怪。我从这里(从下面)获取服务器代码:docs.python.org/2/library/asyncore.html

标签: python python-3.x asynchronous server client


【解决方案1】:

socket 的全部意义在于客户端和服务器之间的send()recv()(接收)数据。连接到服务器后,您必须向服务器发送一些数据(甚至必须发送一个空字符串),服务器可能会向客户端返回一些数据和/或关闭连接。

my_client.py

import socket

sock = socket.socket()
sock.connect(('localhost', 8081))
sock.send(b'data from client')
print(sock.recv(32))
sock.close()

my_server.py

import asyncore
import socket
import time


class EchoHandler(asyncore.dispatcher_with_send):
    def handle_read(self):
        data = self.recv(1024)
        print('data from client', data)
        self.send(b'data from server')
        self.close()


class EchoServer(asyncore.dispatcher):
    def __init__(self, host, port):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.set_reuse_addr()
        self.bind((host, port))
        self.listen(2)

    def handle_accept(self):
        pair = self.accept()
        if pair is not None:
            sock, addr = pair
            print('Incoming connection from %s' % repr(addr))
            handler = EchoHandler(sock)


def main():
    host = 'localhost'
    port = 8081
    server = EchoServer(host, port)

    print('Server %s running' % port)
    asyncore.loop()


if __name__ == '__main__':
    main()

更新:
您确实会收到错误消息:OSError: [WinError 10038],因为您正在关闭服务器中的套接字,而没有从客户端读取所有数据。同样的情况也发生在客户端。
在 Python 文档中明确指出这些是 very basic 示例。

使用方法sendall() 确保发送所有数据。方法send() 不保证所有数据的发送。

您必须使用while 循环从套接字读取数据,如下所示:

my_client.py

import socket

sock = socket.socket()
sock.connect(('localhost', 8081))
sock.sendall(b'data from client')

chunk = b''  # socket.recv returns bytes
data = b''  # defined before to avoid NameError 
while True:
    chunk = sock.recv(32)
    if chunk:
        data += chunk
    else:
        break

print(data)
sock.close()

my_server.py

import asyncore
import socket
import time


class EchoHandler(asyncore.dispatcher_with_send):
    def handle_read(self):

        chunk = b''  # socket.recv returns bytes
        data = b''  # defined before to avoid NameError
        while True:
            chunk = self.recv(1024)
            if chunk:
                data += chunk
            else:
                break

        print('data from client', data)
        self.sendall(b'data from server')
        self.close()


class EchoServer(asyncore.dispatcher):
    def __init__(self, host, port):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.set_reuse_addr()
        self.bind((host, port))
        self.listen(2)

    def handle_accept(self):
        pair = self.accept()
        if pair is not None:
            sock, addr = pair
            print('Incoming connection from %s' % repr(addr))
            handler = EchoHandler(sock)


def main():
    host = 'localhost'
    port = 8081
    server = EchoServer(host, port)

    print('Server %s running' % port)
    asyncore.loop()


if __name__ == '__main__':
    main()

【讨论】:

  • 感谢您的回答!客户端第二次重新启动(服务器正在运行)后,我收到一个异常 (:[WinError 10038]
  • @Viktor 下次请提供完整的错误(包括出现的行)。您不需要 2 周的时间就能得到答复。你很幸运,我有空闲时间检查旧答案! OSError: [WinError 10038] an operation was attempted on something that is not a socket。答案已更新。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-05
  • 2013-05-06
  • 2020-10-09
  • 1970-01-01
  • 2018-11-21
  • 2019-03-17
  • 1970-01-01
相关资源
最近更新 更多