• 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、在粘包的位置客户端随意发送一个值,然后随意接受一个值,并不做任何处理即可。
  • 相关阅读:
    kafka 常见面试题
    分布式-redis实现分布式锁
    java info信息中打印异常堆栈
    11.盛水最多的容器
    445.两数相加
    328. 奇偶链表
    7中join查询
    Linux基础学习05
    Linux基础学习04
    Linux基础学习03
  • 原文地址:https://www.cnblogs.com/cxcx/p/6140297.html
Copyright © 2020-2023  润新知