如何在客户端和服务器(python)中正确关闭套接字 [英] How to properly close socket in both client and server (python)

查看:120
本文介绍了如何在客户端和服务器(python)中正确关闭套接字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用 python 编写 2 个脚本.

I am writing 2 scripts in python.

  1. 客户端.py
  2. Server.py

客户端和服务器之间有一个套接字.场景是这样的:
我有一个客户端要求关闭程序,因此它应该通知服务器,然后服务器将通知另一个客户端,因此我需要关闭从客户端 (1) 到服务器的套接字,然后关闭从服务器到服务器的套接字其他客户(想象一下自己是一个 2 人的游戏,有人要求退出游戏).

There is a socket between the client and server. The scenario is this:
I am having one client that ask to close the program therefore it should inform the server which by then will inform the other client, therefore I need to close the socket from client (1) to the server and then close the socket from the server to other client (imagin yourself a game of 2 people that one ask to exit the game).

我就是这样做的.在 Client.py 中:

I am doing it like that.In Client.py:

# send the request to the server
eNum, eMsg = Protocol.send_all(self.socket_to_server, msg)
if eNum:
    sys.stderr.write(eMsg)
     self.close_client()
self.socket_to_server.shutdown(socket.SHUT_WR) 
exit(0)

然后在Server.py的代码中:

then in the code of Server.py:

# get the msg from the client that calleds
        num, msg = Protocol.recv_all(self.players_sockets[0])

        # case of failure
        if num == Protocol.NetworkErrorCodes.FAILURE:
            sys.stderr.write(msg)
            self.shut_down_server()

        # case it was disconnected
        if num == Protocol.NetworkErrorCodes.DISCONNECTED:
            print msg
            self.shut_down_server()



        technical_win = ("exit" == msg)



        # send the msg to the client needed to call    
        eNum, eMsg = Protocol.send_all(self.players_sockets[1],msg)
        if eNum:
            sys.stderr.write(eMsg)
            self.shut_down_server()

        # case end of game (winning or asking to exit)
        if technical_win:
            self.shut_down_server()

self.shut_down_server() 是:

def shut_down_server(self):

        # close socket of one of the player
        self.players_sockets[0].shutdown(socket.SHUT_RDWR)
        self.players_sockets[0].close()

        # close socket of one of the player
        self.players_sockets[1].shutdown(socket.SHUT_RDWR)
        self.players_sockets[1].close()     

        # clean up
        exit(0)  

当服务器发送其他玩家要求退出的消息时,客户端得到它并按照我在开始时展示的方式进行操作.

When the server send the msg that the other player ask to exit the client get it and doing the same as I showed in the begining.

不幸的是它不起作用,因为当服务器执行代码时:

unfortunately it is not working because when the server perform the code:

num, msg = Protocol.recv_all(self.players_sockets[0])

        # case of failure
        if num == Protocol.NetworkErrorCodes.FAILURE:
            sys.stderr.write(msg)
            self.shut_down_server()

        # case it was disconnected
        if num == Protocol.NetworkErrorCodes.DISCONNECTED:
            print msg
            self.shut_down_server()

它进入第二个 if 并打印 '错误 - 无法接收消息:超时.'

it get into the second if and print 'ERROR - Could not receive a message: timed out.'

我该如何正确解决这个问题?

How do I fix this properly?

附言

我使用的是 Linux

I am using Linux

推荐答案

看起来您正在寻找的是正常关机.首先,您的代码不起作用,因为您在调用 shutdown 后立即关闭了套接字.

It looks like what you are looking for is an graceful shutdown. First your code does not work because you are closing socket immediately after calling shutdown.

规则是,在正常关闭中,双方必须知道关闭并在任何实际关闭套接字之前确认.我只在这个 MSDN 页面,即使它在其他SO 答案中被引用.

The rule is that in a graceful shutdown, both sides must be aware of the shutting down and have acknowledged it before any actually closes the socket. I only found reference for that in this MSDN page, even if it is cited on this other SO answer.

这里是一个简化的演示,如果引用页面更好地解释(我不知道如何在 SO 中正确格式化表格 :-( ) :

Here is a simplified presentation of what is better explained if referenced page (I do not know how to properly format tables in SO :-( ) :

  • 第 1 部分发出 shutdown(socket.SHUT_WR) 通知它要终止连接,并继续从套接字读取
  • 第 2 部分接收套接字上的文件结束指示(空读),并且仍然可以发送任何剩余的数据 - 然后依次调用 shutdown(socket.SHUT_WR)
  • 第 1 部分收到套接字上的文件结尾,并知道其他部分已使用连接终止
  • 然后两个部分都可以关闭套接字
  • part 1 issues shutdown(socket.SHUT_WR) to notify it wants to terminate connexion, and continues to read from socket
  • part 2 receives end of file indication on socket (empty read), and can still send any remaining data - it then calls in turn shutdown(socket.SHUT_WR)
  • part 1 receives end of file on socket and knows that other part has terminated using connection
  • both parts can then close the socket

备注:第 2 部分是否在第 1 部分收到文件结尾之前实际关闭套接字并不重要,因为第 1 部分已经在等待终止的指示:不会丢失任何数据

Remark : it does not matter if part 2 actually closes socket before part 1 received end of file, because part 1 was already only waiting for an indication of termination : no data can have been lost

这篇关于如何在客户端和服务器(python)中正确关闭套接字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆