Проблема с закрытием сервера после выключения, порты продолжают использоваться - PullRequest
0 голосов
/ 10 мая 2019

У меня сейчас работает сервер, который полностью функционален.Но когда я закрываю сервер, сервер не может использовать тот же порт, потому что сокет не был закрыт в скрипте, поэтому я должен сделать вручную:
netstat -ano |findstr: portgoeshere и taskkill / pid portgoeshere / F

Я знаю, что мне нужно использовать следующую команду, чтобы закрыть сокет:
опционально используйте: .shutdown () и обязательно: .close ()

Это код сервера:

class Server:
    ip = socket.gethostbyname(socket.gethostname())
    def __init__(self,host = ip, port=portgoeshere):
        self.socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
        self.socket.setblocking(False)
        self.socket.bind((host,port))

        self.addr_user = {}

    def receive(self):
        while True:
            try:
                data, addr = self.socket.recvfrom(1024)

                if not addr in self.addr_user:
                    user = User(data.decode())
                    scene = logic.getCurrentScene()
                    spawner = scene.objects["Spawner"]
                    avatar = scene.addObject("Avatar", spawner)
                    avatar.children[0]["Text"] = user.name
                    avatar["user"] = user

                    self.addr_user[addr] = user
                else:
                    user = self.addr_user[addr]
                    data = pickle.loads(data)
                    user.keyboard.updateState(data[0])
                    user.mousePosition.updateMousePosition(data[1])


            except socket.error:
                break
    def send(self):
        scene = logic.getCurrentScene()

        state = {(gobj.name, gobj["user"].name): [list(gobj.worldPosition),\
                [gobj.worldOrientation.to_euler().x,gobj.worldOrientation.to_euler().y,gobj.worldOrientation.to_euler().z],\
                [getChildren(gobj).worldOrientation.to_euler().x,getChildren(gobj).worldOrientation.to_euler().y,getChildren(gobj).worldOrientation.to_euler().z]] \
                for gobj in scene.objects \
                if gobj.name == "Avatar"}

        for addr in self.addr_user:
            #print(state)
            self.socket.sendto(pickle.dumps(state),addr)

server = Server()

def receive(self):
    server.receive()

def send():
    server.send()

Это код клиента:

class Client:
    def __init__(self,server_ip ="ipgoeshere", server_port=portgoeshere):
        self.socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
        self.socket.setblocking(False)


        self.serv_addr = (server_ip,server_port)

        self.entities = {}

        self.main = self.state_sendName

    def state_sendName(self):
        scene = logic.getCurrentScene()
        text = scene.objects["Name"]
        if keyHit(events.ENTERKEY):
            self.socket.sendto(bytes(text["Text"],"utf-8"),self.serv_addr)
            text.endObject()
            self.main = self.state_loop

    def state_loop(self):

        self.send()
        self.receive()
        logic.mouse.visible = True
        logic.mouse.position = 0.5,0.5
        scene = logic.getCurrentScene()
        scene.active_camera = scene.objects['AvatarCamera']


    def send(self):
        mouseMovement = logic.mouse.position
        list_key_stat = []
        kevts =  logic.keyboard.events
        for k in kevts:
            s = kevts[k]
            if s in (logic.KX_INPUT_JUST_ACTIVATED, logic.KX_INPUT_JUST_RELEASED):
                list_key_stat.append((k,s))
        if logic.mouse.position is not 0.5:
            self.socket.sendto(pickle.dumps([list_key_stat,mouseMovement]),self.serv_addr)


    def receive(self):
        while True:
            try:
                data, addr = self.socket.recvfrom(1024)

                state = pickle.loads(data)

                for k in state:

                    if not k in self.entities:

                        scene = logic.getCurrentScene()
                        spawner = scene.objects["Spawner"]
                        entity = scene.addObject(k[0], spawner)
                        entity.children[0]["Text"] = k[1]
                        self.entities[k] = entity
                    else:
                        entity = self.entities[k]

                    entity.worldPosition = Vector(state[k][0])
                    entity.worldOrientation = Vector(state[k][1])
                    getChildren(entity).worldOrientation = Vector(state[k][2])




            except socket.error:
                break

client = Client()

Это рабочий код другого клиента:

server = "ipgoeshere"       #Het IP adres van de game
port = portgoeshere     #Het poortnummer

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
    s.bind((server, port))
except socket.error as e:
    str(e)

s.listen(2)
print("Waiting for connection on: ",server,":",port," Server started")


def read_pos(str):
    str = str.split(",")
    return int(str[0]), int(str[1])

def make_pos(tup):
    return str(tup[0]) + "," + str(tup[1])

pos = [(0,0),(100,100)]

def threaded_client(conn, player):
    conn.send(str.encode(make_pos(pos[player])))
    reply = ""
    while True:
        try:
            data = read_pos(conn.recv(2048).decode())
            pos[player] = data

            if not data:
                print("Disconnected")
                break
            else:
                if player == 1:
                    reply = pos[0]
                else:
                    reply = pos[1]

                print("Received : ", data)
                print("Sending : ", reply)

            conn.sendall(str.encode(make_pos(reply)))
        except:
            break

    print("Lost connection")
    conn.close()

currentPlayer = 0

while True:
    conn, addr = s.accept()
    print("Connected to:", addr)


Это то, что я хочуслучиться:

Сервер: Когда сервер отключается, сокет закрывается, поэтому я могу снова использовать тот же порт, когда я хочу повторно инициализировать сервер.

Клиент: Когда клиент выключается, яхотите, чтобы сокет (ТОЛЬКО КЛИЕНТА) был закрыт, чтобы сервер не выключался и клиент мог повторно подключиться к серверу при возникновении проблем.

...