【问题标题】:Socket.close() not closing on serversideSocket.close() 未在服务器端关闭
【发布时间】:2021-03-01 21:44:29
【问题描述】:

我和我的小组使用 Python 和 pygame(学校项目)在 Raspberry Pi 上制作了一个 Wifi-rover。我们得到了一切工作。但是,有一个小问题。关闭 pygame 时,客户端不断向服务器发送垃圾邮件。连接在客户端关闭,但您必须在服务器上手动完成。

树莓派:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

#moduler vi importerer for at kunne bruge pins, LED og socket
from gpiozero import LED
from gpiozero import PWMLED
from time import sleep
import socket
import sys, termios, tty, os

# Setup ports, vi definerer hvilke pins på Ras der anvendes, samt binder dem til variabler

mIn1 = LED(26)
mIn2 = LED(16)
mEn1 = PWMLED(12)
mIn3 = LED(20)
mIn4 = LED(21)
mEn2 = PWMLED(13)



# Global variables - denne starter på 0.0
left = 0.0
right = 0.0

# Function for controlling left motor - her definerer vi hvornår hvilke LED's skal være on og off for at fortælle om den skal køre eller ej
def leftmotor(lspeed):
    if lspeed < 0 :
        mIn1.on()
        mIn2.off()
        mEn1.value = abs(lspeed)
    else :
        mIn1.off()
        mIn2.on()
        mEn1.value = lspeed

# Function for controlling right motor- her definerer vi hvornår hvilke LED's skal være on og off for at fortælle om den skal køre eller ej
def rightmotor(rspeed):
    if rspeed < 0 :
        mIn3.on()
        mIn4.off()
        mEn2.value = abs(rspeed)
    else :
        mIn3.off()
        mIn4.on()
        mEn2.value = rspeed

antalForbindelse = True

# her defineres socket'en - altså vi fortæller at den skal oprette socket og lave variabel der hedder skt
skt = socket.socket()

# host er ip adresse på server (raspberry) port er den port både klient og server lytter på, skal være den samme
HOST = '127.0.0.1'  # Standard loopback interface address (localhost)
PORT = 7000        # Port to listen on (non-privileged ports are > 1023)

# Bind binder host og porten som skal lyttes på - skt.listen fortæller vores server at den skal lytte efter indkommende "pakker"
skt.bind((HOST,PORT))
skt.listen()

# Linie 63 til 65 laver et print hvor den fortæller hvilken IP adresse der er connected og at den ER connected
#Linie 66 til 68 Den fortæller hvilke taster der er trykket på i pygame på clienten og dekoder den inkommende data til bogstaver igen (sendt som bits)
while antalForbindelse:
  forbind, addr = skt.accept()
  print('The client with IP: ', addr, ' has connected')
  while True:
    data = forbind.recv(1024)
    dekodet_data = data.decode('UTF-8')                 
    if dekodet_data =='a':
        left=left +0.1
        leftmotor(left)
        print(left)
    if dekodet_data =='s':
        left=left -0.1
        leftmotor(left)
        print(left)
    if dekodet_data =='f':
        right=right -0.1
        rightmotor(right)
        print(right)
    if dekodet_data =='d':
        right=right +0.1
        rightmotor(right)
        print(right)
    if dekodet_data =='w':
        right = 0.5
        left = 0.5
        rightmotor(right)
        leftmotor(left)
                    
    print('Received', repr(data))
#den nederste linie her fortæller i pygame hvilke tryk der tastes mens server og client kører

客户:

# -*- coding: utf-8 -*-
#moduler vi importerer for at kunne bruge pins, LED og socket
import socket
import pygame

# Laver et display (300, 200) definerer størrelsen og display der viser hvilke tastetryk der trykkes ned i pygame
screen = pygame.display.set_mode((300,200))
pygame.display.set_caption("Tema 2")
gameLoop = True
print("Kører klienten\n")

# her defineres socket'en - altså vi fortæller at den skal oprette socket og lave variabel der hedder skt
skt = socket.socket()

# host er ip adresse på server (raspberry) port er den port både klient og server lytter på, skal være den samme
HOST = '192.168.111.179'  # IP adressen på raspberry pi
PORT = 7000        # Porten den lytter på

# Sender connect anmodningen til server som så svarer at der gerne må deles/sendes data, samt den fortæller hvilken host og port der skal sendes handshake til
skt.connect((HOST,PORT))

#Det burde sende at hvis vi trykker på krydset så skal spillet afsluttes
while gameLoop:
    # Tjek for events (hændelser)
    events = pygame.event.get()
    for event in events:
        # Hvis vi trykker på det røde kryds i højre hjørne, afsluttes spillet
        if event.type == pygame.QUIT:
            gameLoop = False
            skt.close()

#Importerer tastatur tryk fra pygame og encoder dataen til at blive sendt til serveren (på server decodes der og det bliver igen til tastetryk)

        if event.type == pygame.KEYDOWN  and event.key == pygame.K_a:
            msgFromClient = "a"
            indkodet_data = msgFromClient.encode("UTF-8")
            skt.sendall(indkodet_data)
        if event.type == pygame.KEYDOWN  and event.key == pygame.K_s:
            msgFromClient = "s"
            indkodet_data = msgFromClient.encode("UTF-8")
            skt.sendall(indkodet_data)
        if event.type == pygame.KEYDOWN and event.key == pygame.K_d:
            msgFromClient = "d"
            indkodet_data = msgFromClient.encode("UTF-8")
            skt.sendall(indkodet_data)
        if event.type == pygame.KEYDOWN and event.key == pygame.K_f:
            msgFromClient = "f"
            indkodet_data = msgFromClient.encode("UTF-8")
            skt.sendall(indkodet_data)
        if event.type == pygame.KEYDOWN and event.key == pygame.K_b:
            msgFromClient = "b"
            indkodet_data = msgFromClient.encode("UTF-8")
            skt.sendall(indkodet_data)
        if event.type == pygame.KEYDOWN and event.key == pygame.K_w:
            msgFromClient = "w"
            indkodet_data = msgFromClient.encode("UTF-8")
            skt.sendall(indkodet_data)


         #Hvis ikke der bliver tastet en defineret tast men istedet andet tastetryk en asdfwb så printes der ingenting
        else:
            msgFromClient = ""
skt.close() # Lukker forbindelsen

print("Socketen blev lukket")

如果这是一个不好的问题,我提前致歉

【问题讨论】:

  • 请发布一个可重现的最小示例,而不是很可能很快就会过期的粘贴链接。
  • 我已将它们设置为不过期
  • 您应该在问题中使用minimal reproducible example 创建问题,而不是在某些非现场资源上,请参阅第二步 - 完成 - 提供其他人需要在 问题本身
  • 考虑到我不是丹麦人,我不知道这些 cmets 或许多变量是什么意思。我建议你把问题改写成英文。我发现您的代码中有很多问题会导致很多问题,但是由于其中许多行都被注释了,我会假设它解释了为什么代码是这样的并且问题已经得到解决。
  • @TedKleinBergman 说得对

标签: python sockets pygame


【解决方案1】:

服务器不会关闭,因为您从未告诉它这样做。如果服务器会在客户端关闭时关闭,那么就不可能连接多个客户端。

recv 方法将返回客户端发送的消息,如果客户端已关闭连接,则返回 0。因此,只需检查它并在发生这种情况时关闭服务器。

【讨论】:

  • 那么在server.py的底部添加一个skt.close()?
  • 不,你的服务器是一个进程,即一个独立的程序。您需要检查if data == 0:,然后执行任何必要的操作来关闭程序。一个简单的if data == 0: exit() 就足够了。
  • 或者我不知道“skt”是什么,因为这似乎是一个仅存在于您的客户端脚本中的变量。如果它是您的服务器套接字,那么可以,这样做,但这只会关闭套接字。我的假设是你想关闭服务器,而不仅仅是连接,对吧?如果是,请按照我在上面的评论中所说的去做;如果没有,就照你说的做。
  • 你的假设是正确的。我希望服务器在关闭 pygame 时说“套接字已关闭”
  • @Techguy 那么帖子回答了你的问题了吗?在这种情况下,请随意将其标记为已回答。否则,请随时解释缺少的内容,以便我可以编辑更多信息。
猜你喜欢
  • 2011-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-31
  • 1970-01-01
  • 2012-10-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多