Socket套接字方法
socket 实例类(8-10分钟)
socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)
family***(*socke*t家族)***
- socket.AF_UNIX:用于本机进程间通信,为了确定保障程序安全,八个单身的顺序(进程卡塔尔(قطر间是无法互相访问相互的内存的,但为了贯彻进度间的报纸发表,能够由此创制三个地面包车型的士socket来完结
- socket.AF_INET:(还有AF_INET6被用于ipv6,还恐怕有局地任何的地址亲族,可是,他们也许是只用于有个别平台,要么就是早已被打消,或许是比很少被运用,大概是一直未有兑现,全部地方亲族中,AF_INET是利用最遍布的多少个,python协理很种种地点宗族,可是出于大家只关心互连网编制程序,所以超过五分二时候笔者么只利用AF_INET)
socket type***类型***
- socket.SOCK_STREAM #for tcp
- socket.SOCK_DGRAM #for udp
- socket.SOCK_RAW #原始套接字,普通的套接字不可能管理ICMP、I奇霉素P等互连网报文,而SOCK_RAW可以;其次,SOCK_RAW也足以拍卖特别的IPv4报文;其他,利用原始套接字,能够通过IP_HDPAJEROINCL套接字选项由顾客构造IP头。
- socket.SOCK_RDM #是风流洒脱种保证的UDP情势,即确认保证交到数据报但不保障顺序。SOCK_RAM用来提供对原来协议的起码访谈,在急需推行有些特殊操作时行使,如发送ICMP报文。SOCK_RAM经常只限于高档顾客或管理人运营的次第行使。
- socket.SOCK_SEQPACKET #废弃了
(Only SOCK_STREAM and SOCK_DGRAM appear to be generally useful.)
proto=0 请忽视,特殊用场
fileno=None 请忽视,特殊用项
劳务端套接字函数(2分钟卡塔尔国
- s.bind(卡塔尔(قطر绑定(主机,端口号卡塔尔(قطر到套接字
- s.listen(卡塔尔国TCP初阶监听传入连接。backlog钦定在不肯连接此前,能够挂起的最罗安达接数量。 backlog等于5,表示内核已经摄取了接二连三诉求,但服务器还并未有调用accept进行拍卖的总是个数最大为5, 那几个值不可能最佳大,因为要在根本中爱抚连接队列
- s.accept(卡塔尔被动选拔TCP顾客的连年,(堵塞式卡塔尔(قطر等待连接的到来
服务程序调用accept函数从处于监听状态的流套接字s的客户连接请求队列中取出排在最前的一个客户请求,并且创建一个新的套接字来与客户套接字创建连接通道,如果连接成功,就返回新创建的套接字的描述符,以后与客户套接字交换数据的是新创建的套接字;如果失败就返回 INVALID_SOCKET。该函数的第一个参数指定处于监听状态的流套接字;操作系统利用第二个参数来返回新创建的套接字的地址结构;操作系统利用第三个参数来返回新创建的套接字的地址结构的长度。
顾客端套接字函数(2分钟卡塔尔
- s.connect()主动开端化TCP服务器连接
- s.connect_ex(卡塔尔(قطرconnect(卡塔尔函数的扩张版本,出错开上下班时间回来出错码,并非抛出极度
公共用项的套接字函数(3-5分钟卡塔尔国
- s.recv(卡塔尔国选取数据
- s.send(卡塔尔国发送数据(send在待发送数据量大于己端缓存区剩余空间时,数据遗失,不会发完,可前边通过实例解释卡塔尔
- s.sendall(卡塔尔(英语:State of Qatar)发送完整的TCP数据(本质正是循环调用send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不放弃,循环调用send直到发完卡塔尔(英语:State of Qatar)
- s.recvfrom() Receive data from the socket. The return value is a pair (bytes, address)
- s.getpeername()连接到当前套接字的远端的地点
- s.close(卡塔尔(英语:State of Qatar)关闭套接字
- socket.setblocking(flag) #True or False,设置socket为非拥塞情势,现在讲io异步时会用
- socket.getaddrinfo(host, port, family=0, type=0, proto=0, flags=0卡塔尔重返远程主机的地点消息,例子 socket.getaddrinfo('luffycity.com',80卡塔尔(英语:State of Qatar)
- socket.getfqdn(卡塔尔得到本机的主机名
- socket.gethostbyname(卡塔尔(英语:State of Qatar)通过域名深入深入分析ip地址
tcp套接字
1.简单套接字
客户端和服务端:两个主要功能,1、建立链接 2、数据通讯
服务端程序会产生两个套接字socket,一个用于三次握手建立链接,另一个用于收发消息数据通讯;
客户端产生一个套接字socket,既可以用于建立链接后,再用于收发消息数据通讯。
client.py
1 import socket
2
3 #1.买手机
4 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
5 print(phone)
6
7 #2.拨号
8 phone.connect(('127.0.0.1',8081))
9 #端口范围0-65535,0-1024给操作系统用的,若一直无法连接上server,则会一直停留在这一步
10
11 #3.发收消息
12 phone.send('hello'.encode('utf-8'))
13 data = phone.recv(1024)
14 print(data)
15
16 #4.关闭
17 phone.close()
View Code
service.py
1 import socket
2
3 #1.买手机
4 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
5 print(phone)
6
7 #2.绑定手机卡
8 phone.bind(('127.0.0.1',8081)) #端口范围0-65535,0-1024给操作系统用的
9
10 #3.开机
11 phone.listen(5) # 参数表示最大监听数
12
13 #4.等电话链接
14 print('starting...')
15 conn,client = phone.accept() #返回一个新的套接字conn用于通讯,client为发起通讯链接的客户端的ip和端口号
16 print(conn,client)
17 # print('===>')
18
19 #5.收,发消息
20 data = conn.recv(1024) # 单位:bytes, 1024代表最大接收1024个bytes
21 print('客户端的数据',data)
22 conn.send(data.upper())
23
24 #6.挂电话
25 conn.close()
26
27 #7.关机
28 phone.close()
View Code
2.拉长循环套接字
client.py
1 import socket
2
3 #1.买手机
4 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
5
6 print(phone)
7
8 #2.拨号
9 phone.connect(('127.0.0.1',8080)) #端口范围0-65535,0-1024给操作系统用的
10
11 while True:
12 msg = input('>>:').strip()
13 if not msg:continue
14 phone.send(msg.encode('utf-8')) #phone.send(b'')
15 print('has send') #判断能否发空
16 data = phone.recv(1024)
17 print(data.decode('utf-8'))
18
19 #4.关闭
20 phone.close()
View Code
service.py
1 import socket
2
3
4 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
5 phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
6 print(phone)
7 phone.bind(('127.0.0.1',8080)) #端口范围0-65535,0-1024给操作系统用的
8 phone.listen(5) #最大链接挂起数
9
10 print('starting...')
11 conn,client = phone.accept() #监听
12 # print('===>')
13
14 #监听到到后,进行通讯循环
15 # while True:
16 # data = conn.recv(1024) # 单位:bytes, 1024代表最大接收1024个bytes
17 # #conn tcp协议三次握手的成果,双向链接
18 # if not data:break #适用与linux操作,当client单方面终止链接时,service端会出现死循环
19 # print('客户端的数据',data)
20 # conn.send(data.upper())
21
22 while True:
23 try:
24 data = conn.recv(1024) # 单位:bytes, 1024代表最大接收1024个bytes
25 #conn tcp协议三次握手的成果,双向链接
26
27 print('客户端的数据',data)
28 conn.send(data.upper())
29 except ConnectionResetError:
30
31 break
32
33 conn.close()
34 phone.close()
View Code
if not data:break 是用于linux的判断,因为在linux中当client端单方面终止时,servce端会一直接收到空,会一直循环print('客户端的数据',data),因此需要加上判断;
except ConnectionResetError: 是针对windows的,当client端单方面终止时,server端会报ConnnectionRsetError。
有时重启服务端时会遇到报错:
是因为重启时系统尚未来得及回收端口,由此会唤起端口已被并吞。
本条是由于你的服务端依旧存在八次挥手的time_wait状态在挤占地址(即使不懂,请深远斟酌1.tcp三回握手,八遍挥手 2.syn洪流攻击 3.服务器高并发景况下会有恢宏的time_wait状态的优化措施)
清除方法:参预一条socket配置,重用ip和端口。
phone.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind ip和端口 前加。
或者:
实验之前要全部关闭掉所用占用端口的程序,用以下指令
linux:pkill -9 python
windows:taskkill python
3.加上 链接循环
事前代码运行可以知道,client端关闭后,service端也会关闭,但这个时候大家想client端关闭后,service端应该能在吸收接纳新的client端的链接诉求,因而,在建
立链接的一些投入循环。
client.py
1 import socket
2
3 #1.买手机
4 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
5
6 print(phone)
7
8 #2.拨号
9 phone.connect(('127.0.0.1',8080)) #端口范围0-65535,0-1024给操作系统用的
10
11 while True:
12 msg = input('>>:').strip()
13 if not msg:continue
14 phone.send(msg.encode('utf-8')) #phone.send(b'')
15 print('has send') #判断能否发空
16 data = phone.recv(1024)
17 print(data.decode('utf-8'))
18
19 #4.关闭
20 phone.close()
View Code
service.py
1 import socket
2
3 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
4 phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
5 print(phone)
6 phone.bind(('127.0.0.1',8080)) #端口范围0-65535,0-1024给操作系统用的
7 phone.listen(5) #最大链接挂起数
8
9 print('starting...')
10
11 while True:
12 '''
13 用于监听多次client端的链接,但一次链接发起结束后,
14 可继续监听下一次client端的连接
15 '''
16 conn,client = phone.accept()
17 print(client)
18 while True:
19 try:
20 data = conn.recv(1024) # 单位:bytes, 1024代表最大接收1024个bytes
21 #conn tcp协议三次握手的成果,双向链接
22 if not data: break
23 print('客户端的数据',data)
24 conn.send(data.upper())
25 except ConnectionResetError:
26 break
27 conn.close()
View Code
4.模拟ssh远程实施命令
client.py
1 import socket,subprocess
2
3
4 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
5 phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
6 print(phone)
7 phone.bind(('127.0.0.1',9900)) #端口范围0-65535,0-1024给操作系统用的
8 phone.listen(5) #最大链接挂起数
9
10 print('starting...')
11 while True:
12 conn,client = phone.accept() #监听
13
14 while True: #通讯循环
15 try:
16 #1、收命令
17 cmd = conn.recv(1024) # 单位:bytes, 1024代表最大接收1024个bytes
18 #conn tcp协议三次握手的成果,双向链接
19 if not cmd: break
20 #2、执行命令、拿到结果,命令的结果存入stdout=subprocess.PIPE管道,而不是直接输出到终端
21 obj = subprocess.Popen(cmd.decode('utf-8'),shell=True,
22 # 指令由client端发送过来是以utf-8解码为bytes发送过来的,因此处应该以utf-8来编码,
23 # 因此此处的命令编码应该与client端的一致
24 stdout=subprocess.PIPE,
25 stderr=subprocess.PIPE)
26 print(obj)
27 stdout = obj.stdout.read()
28 stderr = obj.stderr.read() #s收发都是bytes格式
29
30 #3、把命令的结果返回给客户端
31 conn.send(stdout+stderr) #申请一块新的内存空间存放stdout+stderr,会占内存,效率会低
32 except ConnectionResetError:
33 break
34 conn.close()
35
36 phone.close()
View Code
service.py
1 import socket
2
3 #1.买手机
4 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
5
6 print(phone)
7
8 #2.拨号
9 phone.connect(('127.0.0.1',9900)) #端口范围0-65535,0-1024给操作系统用的
10
11 while True:
12 msg = input('>>:').strip()
13 if not msg:continue
14 phone.send(msg.encode('utf-8'))
15 # 注意:信息由utf-8解码为bytes格式发送到service端,因此service端也必须把bytes格式以utf-8来编码,
16
17 data = phone.recv(1024) #返回值可能超过1024bytes,
18 print(data.decode('gbk'))
19 # windows上,res.stdout.read()读出的就是GBK编码,因此此处也用GBK编码,linux上默认是utf-8
20
21 #4.关闭
22 phone.close()
View Code
这里注意三个小标题:
1.service端的吩咐的编码应该与client端的解码方式对应,client端以utf-8解码指令为bytes,则service端必得以utf-8来编码;
2.service端的把命令结果发送给client端,client则要求将下令结果进行编码,若serice端在windows上,则以GBK进行编码,若在linux上则以utf-8举办编码。
5.粘包现象解析
事项:独有TCP有粘包现象,UDP长久不会粘包
所谓粘包难点根本照旧因为选取方不晓得音信之间的尽头,不明白三回性领取多少字节的多少所形成的。
udp的recvfrom是梗塞的,贰个recvfrom(x卡塔尔(قطر必需对唯意气风发三个sendinto(y卡塔尔(英语:State of Qatar),收完了x个字节的多少就是实现,倘使y>x数据就不见,那表示udp根本不会粘包,不过会丢数据,不可信。
tcp的说道数据不会丢,未有收完包,后一次接到,会三番若干回上次三回九转选择,己端总是在选取ack时才会覆灭缓冲区内容。数据是可相信的,可是会粘包。
两种状态下会时有产生粘包:
发送端须求等缓冲区满才发送出去,酿成粘包(发送数据时间隔离比超短,数据段超级小,会师到一起,产生粘包)。TCP使用了优化措施(Nagle算法),将每每间隔异常的小且数据量小的数目,合併成多少个大的数据块,然后开展封包。
client.py
1 import socket
2
3 client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
4 client.connect(('127.0.0.1',9903))
5
6 #TCP使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,
7 # 合并成一个大的数据块,然后进行封包。从而在发送端造成粘包。
8 client.send('hello'.encode('utf-8'))
9 client.send('world'.encode('utf-8'))
View Code
service.py
1 import socket
2
3 service = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
4 service.bind(('127.0.0.1',9903))
5 service.listen(5)
6
7 conn,addr = service.accept()
8
9 res1 = conn.recv(1024)
10 print('第一次',res1.decode())
11
12 res2 = conn.recv(1024)
13 print('第二次',res2.decode())
View Code
输出结果:
第一次 helloworld
第二次
发送端由于TCP 优化算法产生粘包
选择方不登时接纳缓冲区的包,变成多个包选拔(顾客端发送了朝气蓬勃段数据,服务端只收了一小部分,服务端后一次再收的时候照旧从缓冲区拿上次遗留的多寡,发生粘包)
client.py
1 #_*_coding:utf-8_*_
2 __author__ = 'Linhaifeng'
3 import socket
4 BUFSIZE=1024
5 ip_port=('127.0.0.1',8080)
6
7 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
8 res=s.connect_ex(ip_port)
9
10
11 s.send('hello feng'.encode('utf-8'))
12
13 客户端
View Code
service.py
1 #_*_coding:utf-8_*_
2 __author__ = 'Linhaifeng'
3 from socket import *
4 ip_port=('127.0.0.1',8080)
5
6 tcp_socket_server=socket(AF_INET,SOCK_STREAM)
7 tcp_socket_server.bind(ip_port)
8 tcp_socket_server.listen(5)
9
10
11 conn,addr=tcp_socket_server.accept()
12
13
14 data1=conn.recv(2) #一次没有收完整
15 data2=conn.recv(10)#下次收的时候,会先取旧的数据,然后取新的
16
17 print('----->',data1.decode('utf-8'))
18 print('----->',data2.decode('utf-8'))
19
20 conn.close()
21
22 服务端
View Code
出口结果
-----> he
-----> llo feng
选取端由于未能一回将发送端叁回发送的多少总体收受,招致粘包
拆包的发生境况
当发送端缓冲区的长度超越网卡的MTU时,tcp会将此次发送的多少拆成多少个数据包发送出去。
补给难题意气风发:为什么tcp是万无一失传输,udp是不可信赖传输
tcp在数据传输时,发送端先把数量发送到自身的缓存中,然后左券决定将缓存中的数据发往对端,对端再次来到叁个ack=1,发送端则清理缓存中的数据,对端重临ack=0,则再次发送数据,所以tcp是牢靠的。
而udp发送数据,对端是不会回来确认音讯的,因而不可相信。
增加补充难点二:send(字节流卡塔尔和recv(1024卡塔尔(قطر及sendall
recv里钦命的1024意思是从缓存里三遍拿出10二十二个字节的数码
send的字节流是先放入己端缓存,然后由协调决定将缓存内容发往对端,假如待发送的字节流大小大于缓存剩余空间,那么数量错失,用sendall就能够循环调用send,数据不会舍弃。
send 和 recv:
1.不管是recv还是send都不是直接接收对方的数据,而是操作自己的操作系统内存-->不是一个send对应一个recv
2.recv阶段,耗时分析:
wait data 耗时非常长
copy data 耗时短
send耗时分析:
copy data
5.粘包消除办法
粘包难题的原故在于接受端不精通发送端就要传送的字节流的尺寸,所以清除粘包的主意正是围绕,怎样让发送端在发送数据前,把团结就要发送的字节流总大小让选拔端知晓,然后选用带来一个死循环接收完全体数据。
首先步:先得到数量的长度
其次步:选择真实的数量
先来介绍下struct模块
该模块能够把七个门类,如数字,转成固定长度的bytes类型
但只顾类型如数字是有约束的,超过范围就能够报错
>>> struct.pack('i',1111111111111)
。。。。。。。。。
struct.error: 'i' format requires -2147483648 <= number <= 2147483647 #以此是限定
1 import struct
2
3 res = struct.pack('i', 1235)
4 print(res,type(res), len(res))
5
6 obj = struct.unpack('i', res)
7 print(obj)
struct 用法
输出结果
b'xd3x04x00x00' <class 'bytes'> 4
(1235,)
在数码发送端将数据长度打包,发送给选择端,解包获取实际多少的尺寸。
轻巧版本报头自制
client.py
1 import socket, struct
2
3 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
4 print(phone)
5
6 phone.connect(('127.0.0.1',9900)) #端口范围0-65535,0-1024给操作系统用的
7
8 while True:
9 #1、发命令
10 msg = input('>>:').strip()
11 if not msg:continue
12 phone.send(msg.encode('utf-8'))
13
14 #2、拿到命令的结果,并打印
15
16 #第一步:先收报头
17 header = phone.recv(4)
18 #第二步:从报头中解析出对真实数据的描述信息
19 total_size = struct.unpack('i',header)[0]
20
21 #第三部:接收真实数据
22 recv_size = 0
23 recv_data = b''
24 while recv_size < total_size:
25 data = phone.recv(1024)
26 recv_data += data
27 recv_size += len(data)
28
29 print(data.decode('gbk'))
30 # windows上,res.stdout.read()读出的就是GBK编码,因此此处也用GBK编码,linux上默认是utf-8
31
32 phone.close()
自制报头
service.py
1 import socket,subprocess,struct
2
3 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
4 phone.bind(('127.0.0.1',9900)) #端口范围0-65535,0-1024给操作系统用的
5 phone.listen(5) #最大链接挂起数
6
7 print('starting...')
8 while True:
9 conn,client = phone.accept() #监听
10
11 while True: #通讯循环
12 try:
13 #1、收命令
14 cmd = conn.recv(1024) # 单位:bytes, 1024代表最大接收1024个bytes
15 #conn tcp协议三次握手的成果,双向链接
16 if not cmd: break
17 #2、执行命令、拿到结果,命令的结果存入stdout=subprocess.PIPE管道,而不是直接输出到终端
18 obj = subprocess.Popen(cmd.decode('utf-8'),shell=True,
19 stdout=subprocess.PIPE,
20 stderr=subprocess.PIPE)
21 print(obj)
22 stdout = obj.stdout.read()
23 stderr = obj.stderr.read() #s收发都是bytes格式
24
25 #3、把命令的结果返回给客户端
26 #第一步:制作固定长度的报头
27 total_size = len(stdout)+len(stderr)
28 header = struct.pack('i', total_size)
29
30 #第二步:把报头(固定长度)发送给客户端
31 conn.send(header)
32
33 #第三步:再发送真实数据
34 conn.send(stdout)
35 conn.send(stderr)
36
37 except ConnectionResetError:
38 break
39 conn.close()
40
41 phone.close()
自制报头
高阶报头自制
如上疏解了简约报头的自制,但有缺欠:
1、报头存有的音讯少。
2、struct模块打包的int数字有节制,普通指令的结果长度尽管不会超越这一个范围,然则上传下载文件时就很有异常的大可能率会当先此限定,因而下边介绍雷同使用struct模块来自制跟高档的报头。
以字典的款型营造报头,字典中得以存文件名、文件md5值、文件大小等,再将字典连串化,将连串化的字符串长度通过struct pack,那样既可让报头存有丰富的新闻,又不会高于struct模块打包的int的数字范围。
client.py
1 import socket, struct, json
2
3 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
4 print(phone)
5
6 phone.connect(('127.0.0.1',9900)) #端口范围0-65535,0-1024给操作系统用的
7
8 while True:
9 #1、发命令
10 msg = input('>>:').strip()
11 if not msg:continue
12 phone.send(msg.encode('utf-8'))
13
14 #2、拿到命令的结果,并打印
15
16 #第一步:先收报头长度
17 obj = phone.recv(4)
18 header_size = struct.unpack('i',obj)[0]
19 # 第二步:再收报头
20 header = phone.recv(header_size)
21
22 #第三步:从报头中解析出对真实数据的描述信息
23 header_dic = json.loads(header)
24 total_size = header_dic['total_size']
25
26 #第三部:接收真实数据
27 recv_size = 0
28 recv_data = b''
29 while recv_size < total_size:
30 data = phone.recv(1024)
31 recv_data += data
32 recv_size += len(data)
33
34 print(data.decode('gbk'))
35 # windows上,res.stdout.read()读出的就是GBK编码,因此此处也用GBK编码,linux上默认是utf-8
36
37 phone.close()
高阶报头自制
service.py
1 import socket, subprocess, struct, json
2
3 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
4 phone.bind(('127.0.0.1',9900)) #端口范围0-65535,0-1024给操作系统用的
5 phone.listen(5) #最大链接挂起数
6
7 print('starting...')
8 while True:
9 conn,client = phone.accept() #监听
10
11 while True: #通讯循环
12 try:
13 #1、收命令
14 cmd = conn.recv(1024) # 单位:bytes, 1024代表最大接收1024个bytes
15 #conn tcp协议三次握手的成果,双向链接
16 if not cmd: break
17 #2、执行命令、拿到结果,命令的结果存入stdout=subprocess.PIPE管道,而不是直接输出到终端
18 obj = subprocess.Popen(cmd.decode('utf-8'),shell=True,
19 stdout=subprocess.PIPE,
20 stderr=subprocess.PIPE)
21 print(obj)
22 stdout = obj.stdout.read()
23 stderr = obj.stderr.read() #s收发都是bytes格式
24
25 #3、把命令的结果返回给客户端
26 #第一步:制作报头
27
28 header_dic = {
29 'filename':'a.txt',
30 'md5':'xxfdxxx',
31 'total_size': len(stdout)+len(stderr)
32 }
33 header_json = json.dumps(header_dic)
34 header_types = header_json.encode('utf-8')
35
36 #第二步:把报头(固定长度)发送给客户端
37 conn.send(struct.pack('i',len(header_types)))
38
39 #第三步:再发送报头、
40 conn.send(header_types)
41
42 #第四步:再发送真实数据
43 conn.send(stdout)
44 conn.send(stderr)
45
46 except ConnectionResetError:
47 break
48 conn.close()
49
50 phone.close()
高阶报头自制
udp 合同套接字
tcp基于链接通讯
- 依附链接,则须求listen(backlog),钦命连接池的深浅
- 根据链接,必需先运转的服务端,然后客商端发起链接诉求
- 对此mac系统:要是黄金年代端断开了链接,那别的生机勃勃端的链接也随之完蛋recv将不会拥塞,收到的是空(杀绝方法是:服务端在收音信后增加if判别,空新闻就break掉通讯循环卡塔尔(قطر
- 对于windows/linux系统:假诺生龙活虎端断开了链接,那其余黄金年代端的链接也随着完蛋recv将不会拥塞,收到的是空(解决办法是:服务端通讯循环内加十二分管理,捕捉到相当后就break掉通讯循环卡塔尔
udp无链接
udp 不需要经过3次握手和4次挥手,不需要提前建立连接,直接发数据就行。
- 无链接,由此无需listen(backlog),尤其未有何样连接池之说了
- 无链接,udp的sendinto不用管是还是不是有八个正值周转的服务端,可以己端四个劲的发音信,只不过数据错过
- recvfrom收的数目低于sendinto发送的数码时,在mac和linux系统上数据直接抛弃,在windows系统上发送的比收受的大一向报错
- 唯有sendinto发送数据未有recvfrom收多少,数据遗失
- 二个sendto对应三个recvfrom,不会发出粘包难题
udp合同纵然不会发出粘包,但 udp左券不安全,tcp左券会在发多少前发个新闻,在接收端回复确认能够接纳数据后,才会发送数据,发送数据 后还要等待接受端回复已吸收后才会一而再三番一遍发送,由此tcp契约是平稳安全的。
client.py
1 import socket
2 # 建立套接字对象
3 client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
4 #client.connect(('127.0.0.0',8080)) #udp没有链接
5
6
7 while True:
8 msg = input('>>:').strip()
9 client.sendto(msg.encode('utf-8'),('127.0.0.1',8080)) #udp没有链接,发送信息必须指定ip和端口
10
11 data,server_addr = client.recvfrom(1024)
12 print(data,server_addr)
13
14 client.close()
udp套接字 client
>>:hah
b'HAH' ('127.0.0.1', 8080)
>>:yy
b'YY' ('127.0.0.1', 8080)
>>:
service.py
1 import socket
2 # 建立套接字对象
3 server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
4 server.bind(('127.0.0.1',8080))
5
6 #server.listen() #监听最大链接数,udp没有链接
7 #server.accept() #建立链接,udp无链接
8
9 while True:
10 data,client = server.recvfrom(1024)
11 print(data,client) #返回数据和数据发送端的ip和端口
12 server.sendto(data.upper(),client) #udp没有链接,发送信息必须指定ip和端口
13
14 server.close()
udp套接字 server
b'hah' ('127.0.0.1', 59001)
b'yy' ('127.0.0.1', 59001)
本文由正版香港马报免费资料发布于首页,转载请注明出处:网络编程
关键词: