基于TCP协议的socket
⼀、套接字socket通信在哪一层
套接字(socket)是⼀个抽象层,应⽤程序可以通过它发送或接受数据,可对其进⾏像⽂件⼀样的打开、读写和关闭等操作。⽹络套接字是IP地址与端⼝的组合。
套接字是⽹络编程中的⼀种通信机制,是⽀持TCP/IP得其⽹络的基本操作单元,可以看做是不同主机之间的进程进⾏双向通信的端点,简单地说就是通信两⽅的⼀种约定,⽤套接字中的相关函数来完成通信过程。
⼆、两种协议
TCP协议
称为流式协议,可靠协议,是⼀种提供可靠数据传输的通⽤协议。
UDP协议
数据报协议(⾃带报头),⼀个⾯向⽆连接的协议。采⽤该协议不需要两个应⽤程序先建⽴连接。不能够提供数据互传,因此还协议传输数据安全新差。
三、TCP通信
tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端
1.socket通信简易版本
服务端
import socket
server = socket.socket()
server.bind(('127.0.0.1',8080))  # 插电话卡绑定IP地址和端⼝(把地址绑定到套接字)
server.listen()  # 开机半连接池
conn,addr = server.accept()  # 接听(接收客户端链接)
data = v(1024)  # 听别⼈说话(接收客户端信息)
print(data)  # 打印客户端信息
conn.send(b'hello girl')  # 给别⼈回话(向客户端发送信息)
conn.close()  # 挂电话(关闭客户端套接字)
server.close()  # 关机(关闭服务器套接字)
server端
客户端
import socket
client = socket.socket()  # 拿电话(创建套接字)
client.send(b'hello boy')  # 对别⼈说话(发送信息)
data = v(1024)  # 听别⼈说话(接受信息)
print(data)  # 打印数据,也就是所得信息
client.close()  # 挂电话(关闭客户端套接字)
client端
2.通信循环
服务端
import socket
server = socket.socket()
server.bind(('127.0.0.1',8080))
server.listen(5)
conn,addr = server.accept()
while True:
data = v(1024)
print(data)
conn.send(data.upper())  # 将客户端传过来的数据转换成⼤写给客户端server端
客户端
import socket
client = socket.socket()
while True:  # 利⽤While 循环来实现
msg = input('>>>:').encode('utf-8')  # 输⼊内容
client.send(msg)  # 将这个内容发送给服务端
data = v(1024)
print(data)  # 打印出这个数据
client端
3.连接循环
服务端
import socket
server = socket.socket()
server.bind(('127.0.0.1',8080))
server.listen(5)  # 5表⽰允许客户端最⼤等待数为5
while True:  # 连接循环上⼀层,下⾯⼀层结束了,返回继续执⾏
conn,addr = server.accept()  # 等待别⼈来
print(addr)  # 打印结果为客户端的ip地址
while True:
try:  # 能够有效地解决服务端报错问题
data = v(1024)
print(data)
if len(data) == 0:
break
conn.send(data.upper())
except ConnectionResetError as e:
print(e)
break
conn.close()
server端
客户端
import socket
client = socket.socket()
while True:
msg = input('>>>:').encode('utf-8')
if len(msg) == 0:
continue
client.send(msg)
data = v(1024)
print(data)
client端
4.代码健壮性补充
问题1
服务端代码
import socket
server = socket.socket()
server.bind(('127.0.0.1',8080))
server.listen(5)
conn,addr = server.accept()
while True:
data = v(1024)
print(data)
conn.send(data.upper())
客户端代码
import socket
client = socket.socket()
while True:  # 利⽤While 循环来实现
msg = input('>>>:').encode('utf-8')  # 输⼊内容
client.send(msg)  # 将这个内容发送给服务端
data = v(1024)
print(data)  # 打印出这个数据
1.先启动服务端,在启动客户端正常运⾏
2.结束客户端后,客户端能够正常退出,服务端会报错
针对于这个问题,就利⽤异常处理的⽅式来解决
客户端代码不变,服务端需要添加 Try 的⽅式来解决,这样服务端也能够正常退出,不会报错
服务端更改后的代码
import socket
server = socket.socket()
server.bind(('127.0.0.1',8080))
server.listen(5)
conn,addr = server.accept()
print(addr)
while True:
try:  # 能够有效地解决服务端报错问题
data = v(1024)
print(data)
if len(data) == 0:
break
conn.send(data.upper())
except ConnectionResetError as e:
print(e)
break
conn.close()
问题2
1.先启动服务端,在启动客户端正常运⾏
产⽣的问题:
会发现点击Enter键的时候,客户端不能够输⼊内容,服务端也⼀直在等待,这样就导致了程序⼀直卡在这了
2.解决⽅法:
在服务端等待的原基础上,对客户端代码进⾏修改,需要对msg进⾏⼀个判断
更改后的代码
import socket
client = socket.socket()
while True:
msg = input('>>>:').encode('utf-8')
if len(msg) == 0:
continue
client.send(msg)
data = v(1024)
print(data)
进⾏判断之后就可以输⼊了
5.TCP粘包问题
问题的根源在于,接收端不知道发送端将要传送的字节流的长度,所以解决粘包的⽅法就是围绕,如何让发送端在发送数据前,把⾃⼰将要发送的字节流总⼤⼩让接收端知晓,然后接收端来⼀个死循环接收完所有数据。
1.使⽤struct模块解决数据繁多冗杂
由上⾯两张图可知,打包之前⽂件⼤⼩为48,打包之后为4,⽆论⽂件⼤⼩是多少,打包结果都是4,
解包之后就会还原成原来⽂件的⼤⼩
2.使⽤struct模块解决TCP粘包问题
借助struct模块,我们知道长度数字可以被转换成⼀个标准⼤⼩的4字节数字。因此可以利⽤这个特点来预先发送数据长度。
服务端
import struct
import subprocess
import socket
import json
server = socket.socket()
server.bind(('127.0.0.1',8080))
server.listen(5)
while True:
conn,addr = server.accept()
while True:
try:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。