Python(八)-Socket与SocketServer

一、 Socket概念

  Socket本质上就是在2台网络互通的电脑之间,架设一个通道,两台电脑通过这个通道来实现数据互相传递。

  我们知道网络通信都是基于IP+Port方能定位目标的具体服务,操作系统有0-65535个端口,每个端口都是独立对外提供服务;建立一个socket必须至少有2端,一个服务端,一个客户端,服务器端被动等待并接收请求,客户端主动发起请求,连接建立后,就可以互相发送数据了。

二、Socket功能类型

  1、Socket Families (地址簇)

    地址簇即地址的种类比如 IPv4、IPv6等。

    Socket.AF_INET      IPv4

    Socket.AF_INET6    IPv6

    Socket.AF_UNIX    Unix本机进程间通信

  2、Socket Types

    Socket类型,例如tcp、udp等

    socket.SOCK_STREAM  表示tcp
    socket.SOCK_DGRAM   表示udp
    socket.SOCK_RAW     原套接字,普通套接字无法处理ICMP、IGMP等网络报文,而SCOK_RAW可以,其次,SOCK_RAW也可以处理特殊的IPV4报文,此外,利用套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头
    socket.SOCK_RDM     是一种可靠的UDP形式,即保证交付数据报单不保证顺序。SOCK_RAM用来提供原始协议的低级访问,在需要执行某些特殊操作时使用,如发送ICMP报文,SOCK_RAM通常仅限于高级用户或者管理员运行的程序使用。
    

  3、Scoket方法

    s = socket.socket(famliy=AF_INET,type=SOCK_STREAM)#声明一个socket
    s.bind(('0.0.0.0',8000))    #绑定IP和端口
    s.listen(5) #监听的请求数
    conn,client_addr = s.accept()   #接受连接并返回,其中conn是新的套接字对象,可以用来接收和发送数据。client_addr是连接客户端的地址,接收Tcp客户的连接(阻塞式)等待连接的到来。
    s.connect(('localhost',8000)) #连接到address的套接字,一般address的格式为元组,如果连接错误,返回socket.ERROR错误。
    s.close #关闭套接字
    s.recv()#接收消息,数据已字符串的形式返回,bufsize指定最多可接收的数量。
    s.send()#将string中的数据发送到连接的套接字,以b的格式发送,但是在返回之前会尝试发送所有数据,成功返回None,失败则抛出异常

  4、SocketServer 方法

  首先定义一个类,然后这个socket类继承Socketserver.BASeRequestHandler,例如

  

    import scocketserver
    class MySocketHandler(socketserver.BaseRequesHandler):
        def handle(self):
            while True:
                self.data = self.request.recv(1024).strip()
                print(self.client_addrss[0])
                print(self.data)
                if not self.data:#这里判断是为了解决,当客户端断开后,服务端循环接受空的数据的。
                    print('client closed...')
                    break
                self.request.send(self.data.upper())#在这里是将接收到的都变为大写返回给客户端。
    if __name__ == '__main__':
        HOST,PORT = '0.0.0.0',9000
        server = socketserver.ThreadingTCPServer((HOST,PORT),MySocketHandler)#这里使用ThreadingTCPServer是同时接受多个客户端的请求,并可以同时接受和发送数据
        server.serve_forever()

  5、Socketserver常见问题

    (1)客户端关闭时,服务端循环接受空值 

这种问题,就可以在服务端返回数据之前做一个判断,判断如果是空值就直接break跳出while循环。
        import socketserver
        class MySocketHandler(socketserver.BaseRequestHandler):
            def handle(self):
                while True:
                    self.data = self.request.recv(1024).strip()
                    print(self.client_address[0])
                    print(self.data)
                    if not self.data:         #在这里解决不接收空值
                        print('client closed...')   
                        break                 
                    self.request.send(self.data.upper())

    (2)socketserver粘包的问题

      

这里有两个解决方法:
    1、在粘包的位置sleep    1-5秒,虽然可以解决粘包的问题,但是通常不会这么干,总体来看,这样会无缘故的降低程序的效率。
    2、在粘包的位置客户端随意发送一个值,然后随意接受一个值,并不做任何处理即可。
原文地址:https://www.cnblogs.com/cxcx/p/6140297.html