当前位置: 首页 > news >正文

上海网站制作技术唐山住房和城乡建设厅网站

上海网站制作技术,唐山住房和城乡建设厅网站,建设银行确认参加面试网站,北京美的网站前言 两个应用程序如果需要进行通讯最基本的一个前提就是能够唯一的标示一个进程#xff0c;我们知道IP层的ip地址可以唯一标示主机#xff0c;而TCP层协议和端口号可以唯一标示主机的一个进程#xff0c;这样我们可以利用ip地址#xff0b;协议#xff0b;端口号唯一标示…前言 两个应用程序如果需要进行通讯最基本的一个前提就是能够唯一的标示一个进程我们知道IP层的ip地址可以唯一标示主机而TCP层协议和端口号可以唯一标示主机的一个进程这样我们可以利用ip地址协议端口号唯一标示网络中的一个进程。能够唯一标示网络中的进程后它们就可以利用socket进行通信了本文将对socket进行介绍。 什么是socket 什么是socket呢我们经常把socket翻译为套接字socket是在应用层和传输层之间的一个抽象层它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用来实现进程在网络中通信。 学习网络编程的目的是为了开发基于互联网通信的软件不论是BS架构的还是CS架构的。我们开发互联网通信软件是处于TCP/IP五层协议中的应用层当涉及到数据需要经过互联网传输时就需要使用到socket抽象层。这个socket抽象层不属于TCP/IP五层是一个抽象的出来的帮我们封装了包括传输层以下的其他各层。它把复杂的TCP/IP协议族隐藏在Socket接口后面对用户来说一组简单的接口就是全部让Socket去组织数据以符合指定的协议。在开发时只需要遵循socket的规定编写代码写出来的程序自然遵循TCP/UDP协议。 套接字发展历史及分类 套接字起源于 20 世纪 70 年代加利福尼亚大学伯克利分校版本的 Unix,即人们所说的 BSD Unix。 因此,有时人们也把套接字称为“伯克利套接字”或“BSD 套接字”。一开始,套接字被设计用在同 一台主机上多个应用程序之间的通讯。这也被称进程间通讯,或 IPC。套接字有两种或者称为有两个种族,分别是基于文件型的和基于网络型的。 基于文件类型的套接字家族 套接字家族的名字AF_UNIX在 unix中一切皆文件基于文件的套接字调用的就是底层的文件系统来取数据两个套接字进程运行在同一机器可以通过访问同一个文件系统间接完成通信。 基于网络类型的套接字家族 套接字家族的名字AF_INET 还有AF_INET6被用于ipv6还有一些其他的地址家族不过他们要么是只用于某个平台要么就是已经被废弃或者是很少被使用或者是根本没有实现所有地址家族中AF_INET是使用最广泛的一个python支持很多种地址家族但是由于我们只关心网络编程所以大部分时候我们只使用AF_INET 。 socket模块 socket可以实现两个网络中的进程进行通信我们可以从日常生活中的例子来对比socket的工作流程比如你要给一个朋友打电话先拨号朋友听到电话铃声后提起电话这时你和你的朋友就建立起了连接就可以讲话了。等交流结束挂断电话结束此次交谈。 生活中的场景就解释了socket的工作原理。 服务端 ​ 1 初始化socket对象 ​ 2 socket对象与服务端的IP和端口绑定bind ​ 3 对端口进行监听(listen) 客户端 ​ 1 初始化socket对象 ​ 2 连接服务器(connect) ​ 3 如果连接成功客户端与服务端的连接就建立了 连接成功后 ​ 1 客户端发送数据请求 ​ 2 服务端接收请求并处理请求 ​ 3 讲回应数据发送给客户端客户端读取数据 ​ 4 关闭连接一次交互结束 python中的socket模块就封装了socket抽象层并提供了一些简单的接口帮助我们实现上述过程。下述代码介绍socket模块的基本使用 补充python查看源码的方式按住ctrl将鼠标悬停在需要查看源码的对象上点击就可以看见源码。 # socket_family 可以是 AF_UNIX 或 AF_INET。socket_type 可以是 SOCK_STREAM 或 SOCK_DGRAM。socket_family默认是-1表示AF_INETsocket_type默认也是-1表示SOCK_STREAM。可以通过源码查看 socket.socket(socket_family, socket_type, protocal0)# 获取tcp/ip套接字 tcp_sock socket.socket(socket.AF_INET, socket.SOCK_STREAM) tcp_sock socket.socket() # 默认就是-1可以不写# 获取udp/ip套接字 udpSock socket.socket(socket.AF_INET, socket.SOCK_DGRAM)socket模块为客户端程序和服务端程序分别提供了不同的方法进行收发数据也提供了一些公用的方法。知道了socket模块的用法我们就可以根据socket模块基于TCP/UDP协议进行开发客户端和服务端的小程序了。我们依次来进行介绍 首先是socket模块为服务端(sever)提供的方法 import sockets socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 获取socket对象 s.bind() # 绑定主机、端口号到套接字 s.listen() # 开始TCP监听 s.accept() # 被动接受TCP客户的连接,(阻塞式)等待连接的到来下面来看socket模块为客户端(client)提供的方法 import sockets socket.socket() # socket对象 s.connect() # 主动初始化连接TCP服务器 s.connect_ex() # connect()函数的扩展版本,出错时返回出错码,而不是抛出异常最后就是一些socket为客户端和服务端提供的一些公共方法 s.recv() # 接收TCP数据 s.send() # 发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完) s.sendall() # 发送完整的TCP数据(本质就是循环调用send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完) s.recvfrom() # 接收UDP数据 s.sendto() # 发送UDP数据 s.getpeername() # 连接到当前套接字的远端的地址 s.getsockname() # 当前套接字的地址 s.getsockopt() # 返回指定套接字的参数 s.setsockopt() # 设置指定套接字的参数 s.close() # 关闭套接字连接基于TCP的套接字 tcp协议的基于双向连接的因此必须先启动服务端然后再启动客户端连接服务器。 先从服务器端说起服务器端先初始化Socket然后与端口绑定(bind)对端口进行监听(listen)调用accept阻塞等待客户端连接。 在这时如果有个客户端初始化一个Socket然后连接服务器(connect)如果连接成功这时客户端与服务器端的连接就建立了。 客户端发送数据请求服务器端接收请求并处理请求然后把回应数据发送给客户端客户端读取数据最后关闭连接一次交互结束。 以上就是一次基于TCP通信的简单流程根据打电话的原理对比具体代码如下 简单版TCP通信 服务端文件 # sever.py 服务端文件 # 以手机接打电话为例 import socket# 1 买手机---获取服务端收发数据的对象 phone socket.socket(socket.AF_INET,socket.SOCK_STREAM)# 2 手机插卡---给服务端绑定IP端口 phone.bind((127.0.0.1,6666))# 3 开机---服务端处于监听状态 phone.listen(3) # 半连接池只能存放三个待确认的连接请求# 4 等待来电---服务端与客户端建立连接建立连接后可以拿到TCP连接的通道信息和客户端的IP和接口 conn,client_addr phone.accept() print(conn) print(客户端IP和接口,client_addr)# 5 电话接通两人愉快的聊天---收发数据 data conn.recv(1024) # 最大接收数据量为1024bytes print(客户端消息, data.decode(utf-8)) conn.send(data.upper())# 6 挂断电话---断开与客户端的连接 conn.close()# 7 手机关机---服务端关机 phone.close()客户端文件 # client.py import socketphone socket.socket(socket.AF_INET,socket.SOCK_STREAM)phone.connect((127.0.0.1,6666))phone.send(show 信息.encode(utf-8))data phone.recv(1024)print(服务端,data.decode(utf-8))phone.close()TCP循环通信 上述简单版的通信代码有一个问题就是费了好大劲才连接成功结果发一句消息连接就断开了就像打电话打一次说一句话挂断电话如果还有没说完的还需要再打.... 为了解决上述问题我们可以使用循环来不断接收或者发送数据 - 循环通讯 服务端文件 # sever.py import socket# 1 买手机---获得服务端的对象 phone socket.socket()# 2 手机插卡---确定服务端的IP和端口 phone.bind((127.0.0.1,7890))# 3 手机开机---服务端进入监听状态 phone.listen(3)# 4 等待接听电话获取TCP通道和客户端的IP和端口conn,client_addr phone.accept()# 5 通电话---收发数据 while True:# 异常处理当防止客户端突然关闭服务端崩溃try:data conn.recv(1024)if not data:breakprint(客户端,data.decode(utf-8))conn.send(data.upper())except Exception:break# 6 挂断电话---服务端与客户端通道断开 conn.close()# 7 关机---服务端关机 phone.close()客户端文件 # client.py import socketphone socket.socket() phone.connect((127.0.0.1, 7890)) while True:info input().strip()# 当发送的数据长度为0时服务端和客户端都会进入等待收数据的阻塞阶段所以进行判断判断用户输入的信息被strip处理后长度是否为0if len(info) 0:continueif info q: breakphone.send(info.encode(utf-8))data phone.recv(1024)print(服务端, data.decode(utf-8))phone.close()服务端不关闭的TCP通信 上述代码方案也存在问题作为服务端应该满足两个条件一是需要为客户端一直提供服务二是并发的提供服务上述循环通信当客户端断开连接后服务端也随之终止运行就无法再向其他客户端提供服务了。因此我们可以让服务端一直处于不关闭的状态。下述为优化后的服务端代码 # sever.py import socketphone socket.socket(socket.AF_INET,socket.SOCK_STREAM)phone.bind((127.0.0.1,65447))phone.listen(5) while True:conn, client_addr phone.accept()while True:try:data conn.recv(1024)if not data:breakprint(客户端,data.decode(utf-8))conn.send(data.upper())except Exception:breakconn.close() # 这里只是断开客户端和服务端的连接当然上述代码也是存在需要优化的地方就是服务端只能同时为一个客户端进行服务如果想要让服务端为多个服务端进行服务需要用到我们后面将要学的知识 - 并发编程。这里就不做过多介绍了。 在使用TCP通信时客户端如果发的消息的空也会出现问题。如果客户端发的消息为空这个消息其实是不会发出去的只是应用程序将这个消息发给了操作系统操作系统收到后发现是空不会往外发的。所以客户端发空后进入recv等状态状态而此时服务端是压根没有收到任何消息也不会回复所以就陷入的尴尬的两边等状态。解决的办法就是判断客户端发的消息是否为空为空直接跳到下一个循环不让这个空消息发给操作系统。 基于UDP的套接字 udp是无链接的先启动哪一端都不会报错。因此它要比基于tcp的套接字在使用上简单很多。 UDP协议是数据报协议发空的时候也会自带报头因此客户端输入空服务端也能收到。 基于udp的套接字是没有连接的客户端和服务端都可以先开启套接字通信也都可以提前结束通信即客户端离开不会影响到服务端的正常运行。 服务端代码 # server.py import socketip_port (127.0.0.1, 8080) server socket.socket(socket.AF_INET, socket.SOCK_DGRAM) server.bind(ip_port) print(服务端开始监听......)while True:get_msg, client_addr server.recvfrom(1024)print(from client:, get_msg)server.sendto(get_msg.upper(), client_addr)# server.close()客户端代码 import socketip_port (127.0.0.1, 8080) client socket.socket(socket.AF_INET, socket.SOCK_DGRAM)while 1:msg input().strip()if msg q:breakif not msg: # 其实udp的套接字支持客户端发空的服务端也能收到空continueclient.sendto(msg.encode(utf-8), ip_port)get_msg, server_addr client.recvfrom(1024)print(get_msg.decode(utf-8)) # 关闭客户套接字TCP协议的粘包问题 粘包问题 首先说明一点TCP有粘包问题UDP没有粘包问题。 发送端可以是1KB地发送数据而接收端的应用程序可以2KB地提走数据当然也有可能一次提走3K或6K数据或者一次只提走几个字节的数据也就是说应用程序所看到的数据是一个整体或说是一个流stream一条消息有多少字节对应用程序是不可见的因此TCP协议是面向流的协议这也是容易出现粘包问题的原因。而UDP是面向消息的协议每个UDP段都是一条消息应用程序必须以消息为单位提取数据不能一次提取任意字节的数据这一点和TCP是很不同的。 TCP是面向连接的面向流的提供高可靠性服务。 收发两端客户端和服务器端都要有一一成对的socket因此发送端为了将多个发往接收端的包更有效的发到对方使用了优化方法Nagle算法将多次间隔较小且数据量小的数据合并成一个大的数据块然后进行封包。 这样接收端就难于分辨出来了必须提供科学的拆包机制。 即面向流的通信是无消息保护边界的。 UDP是无连接的面向消息的提供高效率服务。 不会使用块的合并优化算法, 由于UDP支持的是一对多的模式所以接收端的skbuff(套接字缓冲区采用了链式结构来记录每一个到达的UDP包在每个UDP包中就有了消息头消息来源地址端口等信息。 这样对于接收端来说就容易进行区分处理了。 即面向消息的通信是有消息保护边界的。 **基于TCP协议的粘包问题主要就是因为接收方不知道消息之间的界限不知道每次应该提取多少字节的数据造成的。**总结一下会在两种情况下出现粘包问题 将多次间隔较小且数据量小的数据合并成一个大的数据块然后进行封包造成粘包客户端发送了一段数据服务端只收了一小部分服务端下次再收的时候还是从缓冲区拿上次遗留的数据产生粘包 解决粘包问题 问题的根源在于接收端不知道发送端将要传送的字节流的长度所以解决粘包的方法就是围绕如何让发送端在发送数据前把自己将要发送的字节流总大小让接收端知晓然后接收端来一个循环接收完所有数据。每个消息接收完不留残余。 具体做法是发送端发数据前先将待发的数据长度告知接收端。将数据长度放在一个固定长度的字节中发给接收端接收端先接收这个固定长度的数据头从这个数据头中获悉待接收数据的长度做好循环接收的准备。 可以借助struct模块该模块可以将任意数据类型转换成固定长度的bytes因此借助该模块就可以将发送方发送的数据总大小通过struct模块打包成固定长度的bytes接收端接收后获取发送方发送的数据总大小之后使用循环接收即可。 把报头做成字典字典里包含将要发送的真实数据的详细信息然后json序列化然后用struck将序列化后的数据长度打包成4个字节。 发送时 先发报头长度再编码报头内容然后发送最后发真实内容 接收时 先接收报头长度用struct取出来根据取出的长度收取报头内容然后解码反序列化从反序列化的结果中取出待取数据的详细信息然后去取真实的数据内容。 服务端代码 import subprocess import struct import json import socketserversocket(AF_INET,SOCK_STREAM) server.bind((127.0.0.1,8083)) server.listen(5)# 服务端应该做两件事 # 第一件事循环地从板连接池中取出链接请求与其建立双向链接拿到链接对象 while True:conn,client_addrserver.accept()# 第二件事拿到链接对象与其进行通信循环while True:try:cmdconn.recv(1024)if len(cmd) 0:breakobjsubprocess.Popen(cmd.decode(utf-8),shellTrue,stdoutsubprocess.PIPE,stderrsubprocess.PIPE)stdout_resobj.stdout.read()stderr_resobj.stderr.read()total_sizelen(stdout_res)len(stderr_res)# 1、制作头header_dic{filename:a.txt,total_size:total_size,md5:1111111111}json_str json.dumps(header_dic)json_str_bytes json_str.encode(utf-8)# 2、先把头的长度发过去xstruct.pack(i,len(json_str_bytes))conn.send(x)# 3、发头信息conn.send(json_str_bytes)# 4、再发真实的数据conn.send(stdout_res)conn.send(stderr_res)except Exception:breakconn.close()客户端代码 import struct import json from socket import *clientsocket(AF_INET,SOCK_STREAM) client.connect((127.0.0.1,8083))while True:cmdinput(cmd).strip()if len(cmd) 0: continueclient.send(cmd.encode(utf-8))# 接收端# 1、先收4个字节从中提取接下来要收的头的长度x client.recv(4)header_lenstruct.unpack(i,x)[0]# 2、接收头并解析json_str_bytesclient.recv(header_len)json_strjson_str_bytes.decode(utf-8)header_dicjson.loads(json_str)print(header_dic)total_sizeheader_dic[total_size]# 3、接收真实的数据recv_size 0while recv_size total_size:recv_dataclient.recv(1024)recv_sizelen(recv_data)print(recv_data.decode(utf-8),end)else:print() 最后感谢每一个认真阅读我文章的人礼尚往来总是要有的这些资料对于【软件测试】的朋友来说应该是最全面最完整的备战仓库虽然不是什么很值钱的东西如果你用得到的话可以直接拿走 这些资料对于【软件测试】的朋友来说应该是最全面最完整的备战仓库这个仓库也陪伴上万个测试工程师们走过最艰难的路程希望也能帮助到你
http://www.zqtcl.cn/news/362880/

相关文章:

  • 公司网站维护怎么维护东莞网站建设it s
  • pc网站怎么做男科医院治疗一次2000元
  • 电子网站建设心得企业查询app排行榜
  • 杭州做网站的科技公司永川做网站的公司
  • 动物自己做的网站网站优化外包公司
  • 企业网站建设的三种方式并举例手机wap网站是什么
  • 做深圳门户网站起什么名字好建设网站对公司起什么作用是什么
  • 长春企业网站设计建设公司资质查询官网
  • 医疗网站前置审批查询免费网站建设可信赖
  • 摄影师个人网站模板宝坻集团网站建设
  • 比较多人用什么网站做推广wordpress数据库表管理系统
  • 网页开发和游戏开发东莞优化怎么做seo
  • 北京网站搭建开发高级网页设计教程
  • 北京南站是中高风险地区吗网站建设上机实验心得
  • 大学生做兼职的网站有哪些免费行情软件网站有哪些
  • 静安手机网站建设常见的网络营销方法及其效果
  • 怎么改版网站湖南长沙地图
  • 中卫网站推广公司如何自创app软件
  • 无棣网站建设电子商务网站设计原理书籍
  • 做t-shirt素材网站企业网站建设结论
  • 唐山公司做网站查询建筑资质的网站
  • 邯郸的网站建设网站正能量入口
  • 网站导航栏最多可以做几个宝安网站设计排名
  • 自己怎样用手机建网站网件app
  • 周口网站开发西安市建设厅网站
  • 怎么授权小说做游戏网站论坛网站开发语言
  • 烟台商城网站建设怎么样引流顾客到店方法
  • 北京做网站公司的排名python基础教程pdf
  • 网站建设为什么学flash建设工程询价网站有哪些
  • 网站内容建设机制企业管理模式有哪些