1、socket 1、socket层2、socket的理解 写python代码的时候socket就像是一个模块,经过import导入,经过调用模块中的方法创建两个进程之间的链接和通讯。 Socket是应用层与传输层通讯的中间软件抽象层,它是一组接口。它是为了帮咱们简化两个进程之间通讯的步骤, 使用Socket不须要咱们很了解网络层、数据链路层等底层的工做原理,Socket已经帮咱们把那些复杂的通讯过程封装好了, 咱们直接去使用就好了 3、套接字(socket)的发展史 套接字起源于 20 世纪 70 年代加利福尼亚大学伯克利分校版本的 Unix,即人们所说的 BSD Unix。 所以,有时人们也把套接字称为“伯克利套接字”或“BSD 套接字”。 一开始,套接字被设计用在同 一台主机上多个应用程序之间的通信。这也被称进程间通信,或 IPC。 套接字有两种(或者称为有两个种族),分别是基于文件型的和基于网络型的。 基于文件类型的套接字家族 套接字家族的名字:AF_UNIX unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,能够经过访问同一个文件系统间接完成通讯 基于网络类型的套接字家族 套接字家族的名字:AF_INET (还有AF_INET6被用于ipv6,还有一些其余的地址家族,不过,他们要么是只用于某个平台,要么就是已经被废弃,或者是不多被使用,或者是根本没有实现, 全部地址家族中,AF_INET是使用最普遍的一个,python支持不少种地址家族,可是因为咱们只关心网络编程,因此大部分时候我么只使用AF_INET) 四、基于tcp/udp的socket TCP:可靠的、面向链接的协议、传输效率低全双工通讯(发送缓存&接收缓存)、面向字节流。使用TCP的应用:Web浏览器;电子邮件、文件传输程序。 UDP:不可靠的、无链接的服务,传输效率高,一对1、一对多、多对1、多对多、面向报文,尽最大努力服务,无拥塞控制。使用UDP的应用:域名系统 (DNS);视频流;IP语音(VoIP)。
5、小例子 5-1、tcp协议的socket
对于TCP协议的socket server来讲 不能同时接受多个client端的链接# 服务端 import socket # 导入socket tcp_sk = socket.socket() # 实例化一个服务器对象 tcp_sk.bind(('127.0.0.1',8080)) # 服务器绑定一个IP地址和端口 tcp_sk.listen() # 监听链接 # conn能够理解为在服务端中与客户端进行交互的操做符(对象) # addr是客户端的IP地址和端口 conn,addr = tcp_sk.accept() # 接受客户端连接,此时若是没有客户端链接过来,服务器会在此等候,不会向下走(阻塞) while True: se_msg = input('>>>:') conn.send(se_msg.encode('utf-8')) # send发送的内容必须是bytes类型 re_msg = conn.recv(1024) # recv接收客户端发送过来的内容,1024是接收的字节长度 print(re_msg.decode('utf-8')) conn.close() # 关闭与客户端的链接 tcp_sk.close() # 关闭服务器 # 注意:通常状况下服务器是不会关闭的,会一直为用户提供服务。 # 客户端 import socket sk = socket.socket() # 实例化一个客户端对象 sk.connect(('127.0.0.1',8080)) # 链接服务端的IP和端口 while True: re_msg = sk.recv(1024) print(re_msg.decode('utf-8')) se_msg = input('>>>:') sk.send(se_msg.encode('utf-8')) sk.close() # 关闭客户端 注意:服务器和客户端的send,recv是一一对应的,也就是说,服务器send一次,客户端就须要recv一次, 客户端send一次,服务端也要recv一次。 客户端只须要链接上服务器就能够了,客户端的IP就是本身的IP,可是端口是由操做系统随机分配的。 tcp是基于连接的,必须先启动服务端,而后再启动客户端去连接服务端 还有的时候会遇到这种错误状况:
错误的意思是说你这个端口被占用了,引起的缘由多是由于,你运行服务端后直接按pycharm的强制退出键,致使操做系统并无 第一时间知道你已经结束了这个程序,若是不急用这个端口的话,你能够等上几分钟,操做系统会反应过来你已经不须要这个程序了, 会自动帮你释放这个端口,或者你能够改一个端口使用,若是你很任性,你就要马上立刻使用这个端口,那么能够这样: 在bind以前加入一条socket配置,重用ip和端口 tcp_sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # 就是这个东西 tcp_sk.bind(('127.0.0.1',8080)) 可退出的: 服务端: import socket sk = socket.socket() sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) sk.bind(('127.0.0.1',8085)) sk.listen() while True: conn,addr = sk.accept() while True: se_msg = input('>>>:') conn.send(se_msg.encode('utf-8')) if se_msg == 'q': break re_msg = conn.recv(1024) if re_msg == b'q': break print(re_msg.decode('utf-8')) conn.close() sk.close 客户端: import socket sk = socket.socket() sk.connect(('127.0.0.1',8085)) while True: re_msg = sk.recv(1024) if re_msg == b'q': break print(re_msg.decode('utf-8')) se_msg = input('>>>:') sk.send(se_msg.encode('utf-8')) if se_msg == 'q': break sk.close() 5-2、udp的socket
server端 import socket sk = socket.socket(type=socket.SOCK_DGRAM) # 设置type使其成为udp类型的socket sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) sk.bind(('127.0.0.1',8005)) # 绑定IP和端口 msg,addr = sk.recvfrom(1024) # 接收信息和对方IP print(msg.decode('utf-8')) print(addr) sk.sendto('你好'.encode('utf-8'),addr) # 发送信息给对方 sk.close() client端: import socket sk = socket.socket(type=socket.SOCK_DGRAM) sk.sendto('hello'.encode('utf-8'),('127.0.0.1',8005)) msg,addr = sk.recvfrom(1024) print(msg.decode('utf-8')) print(addr) sk.close() 注意:udp支持多个客户端同时与服务端交互, 可是开始发送消息的一方确定是客户端,由于客户端不传送消息给服务端,服务端是 不知道客户端的IP的,是没法通讯的,因此要通讯,只能客户端先发起请求。 循环模式: 服务端: import socket sk = socket.socket(type=socket.SOCK_DGRAM) # 设置type使其成为udp类型的socket sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) sk.bind(('127.0.0.1',8005)) # 绑定IP和端口 while True: msg,addr = sk.recvfrom(1024) # 接收信息和对方IP print(addr,msg.decode('utf-8')) msg_send = input('>>>:') sk.sendto(msg_send.encode('utf-8'),addr) # 发送信息给对方 sk.close() 客户端: import socket sk = socket.socket(type=socket.SOCK_DGRAM) while True: msg_send = input('>>>:') sk.sendto(msg_send.encode('utf-8'),('127.0.0.1',8005)) msg,addr = sk.recvfrom(1024) print(addr,msg.decode('utf-8')) sk.close()
六、socket参数详解
family | 地址系列应为AF_INET(默认值),AF_INET6,AF_UNIX,AF_CAN或AF_RDS。 (AF_UNIX 域其实是使用本地 socket 文件来通讯) |
type | 套接字类型应为SOCK_STREAM(默认值),SOCK_DGRAM,SOCK_RAW或其余SOCK_常量之一。 SOCK_STREAM 是基于TCP的,有保障的(即能保证数据正确传送到对方)面向链接的SOCKET,多用于资料传送。 SOCK_DGRAM 是基于UDP的,无保障的面向消息的socket,多用于在网络上发广播信息。 |
proto | 协议号一般为零,能够省略,或者在地址族为AF_CAN的状况下,协议应为CAN_RAW或CAN_BCM之一。 |
fileno | 若是指定了fileno,则其余参数将被忽略,致使带有指定文件描述符的套接字返回。 与socket.fromfd()不一样,fileno将返回相同的套接字,而不是重复的。 这可能有助于使用socket.close()关闭一个独立的插座。 |
2、软件开发的架构 一、C/S架构:server client Client与Server就是客户端与服务器端的意思,这里的客户端一般指的是咱们的应用程序二、B/S架构 Browser与Server就是浏览器端与服务器端架构,Browser指的是浏览器,其实也是一种Client客户端,只是这个客户端不须要你们去安装什么应用程序, 只需在浏览器上经过HTTP请求服务器端相关的资源(网页资源),客户端Browser浏览器就能进行增删改查。
三、b/s的趋势 随着咱们要安装的应用程序愈来愈多,咱们就会感受很麻烦,若是能像浏览器同样,只打开浏览器就能够访问各类资源,那么久方便不少了, 因此手机端也是向着b/s方向发展的(微信小程序就是一个很好的例子,只要打开微信,在微信搜索须要的应用便可,不须要额外打开其余程序) pc端 浏览器 统一了程序的入口 手机端 微信小程序 统一了程序的入口