27_网络编程-初识socket
一、C/S B/S 架构
1、定义
(1)C/S结构,即Client/Server(客户机/服务器)结构,是大家熟知的软件系统体系结构,通过将任务合理分配到Client端和Server端,降低了系统的通讯开销,可以充分利用两端硬件环境的优势。早期的软件系统多 以此作为首选设计标准。
(2)B/S结构,即Browser/Server(浏览器/服务器)结构,是随着Internet技术的兴起,对C/S结构的一种变化或者改进的结构。在这种结构下,用户界面完全通过WWW浏览器实现,一部分事务逻辑在前端实现,但是 主要事务逻辑在服务器端实现,形成所谓3-tier结构。
B/S结构,主要是利用了不断成熟的WWW浏览器技术,结合浏览器的多种scrīpt语言(VBscrīpt、Javascrīpt…)和ActiveX技术,用通用浏览器就实现了原来需要复杂专用软件才能实现的强大功能,并节约了开发成 本,是一种全新的软件系统构造技术。随着Windows 98/Windows 2000将浏览器技术植入操作系统内部,这种结构更成为当今应用软件的首选体系结构。
2、区别
Client/Server是建立在局域网的基础上的.Browser/Server是建立在广域网的基础上的.
(1).硬件环境不同
C/S 一般建立在专用的网络上, 小范围里的网络环境, 局域网之间再通过专门服务器提供连接和数据交换服务.
B/S 建立在广域网之上的, 不必是专门的网络硬件环境,例如电话上网, 租用设备. 信息管理. 有比C/S更强的适应范围, 一般只要有操作系统和浏览器就行
(2).对安全要求不同
C/S 一般面向相对固定的用户群, 对信息安全的控制能力很强. 一般高度机密的信息系统采用C/S 结构适宜. 可以通过B/S发布部分可公开信息.
B/S 建立在广域网之上, 对安全的控制能力相对弱, 面向是不可知的用户群.
(3).对程序架构不同
C/S 程序可以更加注重流程, 可以对权限多层次校验, 对系统运行速度可以较少考虑.
B/S 对安全以及访问速度的多重的考虑, 建立在需要更加优化的基础之上. 比C/S有更高的要求 B/S结构的程序架构是发展的趋势, 从MS的.Net系列的BizTalk 2000 Exchange 2000等, 全面支持网络的构件搭建的系统. SUN 和IBM推的JavaBean 构件技术等,使 B/S更加成熟.
(4).软件重用不同
C/S 程序可以不可避免的整体性考虑, 构件的重用性不如在B/S要求下的构件的重用性好.
B/S 对的多重结构,要求构件相对独立的功能. 能够相对较好的重用.
(5).系统维护不同
系统维护在是软件生存周期中,开销大, -------重要
C/S 程序由于整体性, 必须整体考察, 处理出现的问题以及系统升级. 升级难. 可能是再做一个全新的系统
B/S 构件组成,方面构件个别的更换,实现系统的无缝升级. 系统维护开销减到最小.用户从网上自己下载安装就可以实现升级.
(6).处理问题不同
C/S 程序可以处理用户面固定, 并且在相同区域, 安全要求高需求, 与操作系统相关. 应该都是相同的系统
B/S 建立在广域网上, 面向不同的用户群, 分散地域, 这是C/S无法作到的. 与操作系统平台关系最小.
(7).用户接口不同
C/S 多是建立的Window平台上,表现方法有限,对程序员普遍要求较高
B/S 建立在浏览器上, 有更加丰富和生动的表现方式与用户交流. 并且大部分难度减低,减低开发成本.
二、socket
1、图
2、socket定义
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
socket就是一个模块。我们通过调用模块中已经实现的方法建立两个进程之间的连接和通信。也有人将socket说成ip+port,因为ip是用来标识互联网中的一台主机的位置,而port是用来标识这台机器上的一个应用程序。所以我们只要确立了ip和port就能找到一个应用程序,并且使用socket模块来与之通信
3、socket发展史
套接字起源于 20 世纪 70 年代加利福尼亚大学伯克利分校版本的 Unix,即人们所说的 BSD Unix。 因此,有时人们也把套接字称为“伯克利套接字”或“BSD 套接字”。一开始,套接字被设计用在同 一台主机上多个应用程序之间的通讯。这也被称进程间通讯,或 IPC。套接字有两种(或者称为有两个种族),分别是基于文件型的和基于网络型的
(1)基于文件类型的套接字家族 - AF_UNIX
unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信
(2)基于网络类型的套接字家族 - AF_INET
(还有AF_INET6被用于ipv6,还有一些其他的地址家族,不过,他们要么是只用于某个平台,要么就是已经被废弃,或者是很少被使用,或者是根本没有实现,所有地址家族中,AF_INET是使用最广泛的一个,python支持很多种地址家族,但是由于我们只关心网络编程,所以大部分时候我么只使用AF_INET)
三、socket编程
1、服务端
1 import socket 2 sk = socket.socket() 3 sk.bind(('127.0.0.1',8898)) #把地址绑定到套接字 4 sk.listen() #监听链接 5 conn,addr = sk.accept() #接受客户端链接 6 ret = conn.recv(1024) #接收客户端信息 7 print(ret) #打印客户端信息 8 conn.send(b'hi') #向客户端发送信息 9 conn.close() #关闭客户端套接字 10 sk.close() #关闭服务器套接字(可选)
2、客户端
1 import socket 2 sk = socket.socket() # 创建客户套接字 3 sk.connect(('127.0.0.1',8898)) # 尝试连接服务器 4 sk.send(b'hello!') 5 ret = sk.recv(1024) # 对话(发送/接收) 6 print(ret) 7 sk.close() # 关闭客户套接字
重启服务端是会出现:OSError:[Errno 48] Address already in use, 解决方案
1 #加入一条socket配置,重用ip和端口 2 import socket 3 from socket import SOL_SOCKET,SO_REUSEADDR 4 sk = socket.socket() 5 sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加 6 sk.bind(('127.0.0.1',8898)) #把地址绑定到套接字 7 sk.listen() #监听链接 8 conn,addr = sk.accept() #接受客户端链接 9 ret = conn.recv(1024) #接收客户端信息 10 print(ret) #打印客户端信息 11 conn.send(b'hi') #向客户端发送信息 12 conn.close() #关闭客户端套接字 13 sk.close() #关闭服务器套接字(可选)
四、socket实例
1、一直输入对话
服务端
1 import socket 2 from socket import SOL_SOCKET,SO_REUSEADDR 3 while 1: 4 server = socket.socket() # 创建服务器对象 5 server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) 6 ip_port = ('192.168.15.202',8001) # 设置服务器段ip port 7 server.bind(ip_port) # 绑定ip port 8 server.listen(3) # 监听ip,端口,看看监听谁来访问我;参数是设置允许最多10个客户端来访问我。源码默认128一分组,不限制 9 print('等待连接...') 10 conn, address = server.accept() # 阻塞在这里,等待客户端的链接 , conn 是服务器与客户端的链接通道,后面接收/发送都需要使用此变量 11 print('连接成功!') 12 13 while 1 : 14 15 from_client_msg = conn.recv(1024) # 接收客户端的消息,设置接收数据大小,单位是字节 16 print(from_client_msg.decode('utf-8')) # 接收的是bytes类型的,需要解码 17 if from_client_msg.decode('utf-8') == 'close': 18 break 19 msg = input('请返回数据>>>') 20 conn.send(msg.encode('utf-8')) # 向客户端发送消息bytes类型,需编码
客户端
1 import socket 2 client = socket.socket() 3 from_server_port = ('192.168.15.202',8001) # 设置需要访问的服务器端ip port 4 5 client.connect(from_server_port) # 去链接服务器端ip port 6 while 1: 7 msg = input('>>>') 8 client.send(msg.encode('utf-8')) # 向服务器端发送信息,需编码 9 if msg == 'close': 10 break 11 content_server = client.recv(1024) # 接收服务器发过来的消息 12 print(content_server.decode('utf-8')) # 将接收的消息进行解码 13 client.close()