Socket
- socket模块是针对 服务器端 和 客户端Socket 进行【打开】【读写】【关闭】。
1 #!/usr/bin/env python 2 #coding=utf-8 3 __author__ = 'yinjia' 4 5 6 import socket 7 8 ip_port = ('127.0.0.1',9999) 9 10 sk = socket.socket() 11 sk.bind(ip_port) 12 sk.listen() 13 14 while True: 15 print("等待连接......") 16 con,addr = sk.accept() 17 18 client_data = str(con.recv(1024),encoding='utf-8') 19 print(client_data) 20 con.sendall(bytes("不想回答!",encoding='utf-8')) 21 22 con.close()
1 #!/usr/bin/env python 2 #coding=utf-8 3 __author__ = 'yinjia' 4 5 6 import socket 7 8 ip_port = ('127.0.0.1',9999) 9 10 sk = socket.socket() 11 sk.connect(ip_port) 12 13 sk.sendall(bytes("您好,请回答问题!",encoding='utf-8')) 14 15 server_reply = sk.recv(1024) 16 print(str(server_reply,encoding='utf-8')) 17 18 sk.close()
- sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0)
1 参数一:地址簇 2 3 socket.AF_INET IPv4(默认) 4 socket.AF_INET6 IPv6 5 6 socket.AF_UNIX 只能够用于单一的Unix系统进程间通信 7 8 参数二:类型 9 10 socket.SOCK_STREAM 流式socket , for TCP (默认) 11 socket.SOCK_DGRAM 数据报式socket , for UDP 12 13 socket.SOCK_RAW 原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。 14 socket.SOCK_RDM 是一种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RAM用来提供对原始协议的低级访问,在需要执行某些特殊操作时使用,如发送ICMP报文。SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。 15 socket.SOCK_SEQPACKET 可靠的连续数据包服务 16 17 参数三:协议 18 19 0 (默认)与特定的地址家族相关的协议,如果是 0 ,则系统就会根据地址格式和套接类别,自动选择一个合适的协议
SocketServer
- SocketServer内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,从而实现并发处理多个客户端请求的Socket服务端。即:每个客户端请求连接到服务器时,Socket服务端都会在服务器是创建一个“线程”或者“进程” 专门负责处理当前客户端的所有请求。
ThreadingTCPServer实现的Soket服务器内部会为每个client创建一个 “线程”,该线程用来和客户端进行交互。
1 #!/usr/bin/env python 2 #coding=utf-8 3 __author__ = 'yinjia' 4 5 import socketserver 6 7 class MyServer(socketserver.BaseRequestHandler): 8 9 def handle(self): 10 conn = self.request 11 teacher = "老师说:" 12 13 14 conn.sendall(bytes('欢迎使用选课系统!', encoding='utf-8')) 15 #连接客户端地址信息 16 while True: 17 print("server waiting...") 18 ret_bytes = conn.recv(1024) 19 ret_str = str(ret_bytes,encoding='utf-8') 20 if ret_str.lower() == 'q': 21 break 22 conn.sendall(bytes(teacher + '好',encoding='utf-8')) 23 24 if __name__ == '__main__': 25 server = socketserver.ThreadingTCPServer(('127.0.0.1',9999),MyServer) 26 server.serve_forever()
1 #!/usr/bin/env python 2 #coding=utf-8 3 __author__ = 'yinjia' 4 5 6 import socket 7 ip_port = ('127.0.0.1',9999) 8 9 10 sk = socket.socket() 11 sk.connect(ip_port) 12 13 ret_bytes = sk.recv(1024) 14 ret_str = str(ret_bytes,encoding='utf-8') 15 print(ret_str) 16 17 while True: 18 inp = str(input("发送:")) 19 if inp.lower() == 'q': 20 sk.sendall(bytes(inp,encoding='utf-8')) 21 break 22 else: 23 sk.sendall(bytes(inp,encoding='utf-8')) 24 ret = str(sk.recv(1024),encoding='utf-8') 25 print(ret) 26 sk.close()
ForkingTCPServer和ThreadingTCPServer的使用和执行流程基本一致,只不过在内部分别为请求者建立 “进程” 和 “线程”。
ForkingTCPServer只是将 ThreadingTCPServer 实例中的代码如下:
1 server = socketserver.ThreadingTCPServer(('127.0.0.1',9999),MyServer) 2 变更为: 3 server = socketserver.ForkingTCPServer(('127.0.0.1',9999),MyServer)
其实本质上就是在服务器端为每一个客户端创建一个进程,当前新创建的进程用来处理对应客户端的请求,所以,可以支持同时n个客户端链接(长连接)。