首页 > 其他 > 详细

d28 scoket套接字 struct模块

时间:2019-08-07 23:24:13      阅读:93      评论:0      收藏:0      [点我收藏+]

scoket套接字

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口

 

技术分享图片

 

 服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束

 

 scoket模块

技术分享图片
import socket
# 生成对象
server = socket.socket()
# 绑定ip和端口
server.bind((127.0.0.1,8080))
#绑定参数为一个元组
#127.0.0.1这叫回送地址  表示电脑本身   端口 为普通整数 一般为8000以上
# 监听  半连接池
server.listen(5)
# 接收链接请求
# 第一个是表示客户端的socket    第二个客户端的地址信息
conn,addr = server.accept()
#接收字节
data = conn.recv(1024)
print(data)
# 发送数据
conn.send(bhello  world)
# 关闭
conn.close()
# 关机
server.close()
服务端
技术分享图片
import socket

client = socket.socket()
# 连接服务端
client.connect((127.0.0.1,8080))
#发送数据
client.send(bni hao)
# 接收数据
data = client.recv(1024)

print(data)
# 关闭
client.close()
客户端

 

accept  是一个阻塞函数  会一直等到有客户端链接过来 在继续执行
connect本质实在进行三次握手   也是一个数据传输的过程  如果服务器没有立马响应 也会阻塞

 send

发送数据 本质上是把数据交给操作系统来进行发送 一旦数据交给了操作系统 后续的发送

应用程序就无法控制了 ,send一般不会卡 当然 如果数据量很大就会阻塞

scoket套接字是从操作系统缓存区读取数据   
如果当前还没有任何数据, 就会进入阻塞会一直等到有数据到来 再继续执行

  

send与recv对应,不要出现两边都是相同的情况

  

异常

# 如果已经开启了服务器  再次运行将会抛出 端口占用异常  把之前开启的服务器关掉即可
1.可能是由于你已经启动了服务器程序,却又再次启动了服务器程序,同一个端口不能被多个进程使用导致!

2.三次握手或四次挥手时,发生了异常导致对方程序已经结束而服务器任然处于time_wait状态导致!

3.在高并发的场景下,由于链接的客户端太多,也会产生大量处于time_wait状态的链接

 升级版

技术分享图片
import socket
# 产生对象
server = socket.socket()
# 绑定ip和端口
server.bind((127.0.0.1,8080))
# 监听
server.listen(5)
while True:
    # 接收
    conn,addr = server.accept()
    # print(conn)
    # print(addr)
    # 接收
    while True:
        try:
            data = conn.recv(1024)
            print(data)
            # 防止客户端发生异常或断掉
            if len(data) == 0:
                break
            conn.send(data.upper())
        except ConnectionResetError as a:
            print(a)
            break
    conn.close()
服务端
技术分享图片
import socket
# 产生对象
client = socket.socket()
# 绑定
client.connect((127.0.0.1,8080))
while True:
    # 输入的信息为字符串类型,传输数据是由二进制数据传送的
    msg = input(>>>..).encode(utf-8)
    # 防止输入的信息为空
    if len(msg) == 0:
        continue
    client.send(msg)
    data = client.recv(1024)
    print(data)
客户端

TCP粘包问题

TCP流式协议, 数据之间没有分界, 就像水  一杯水和一杯牛奶倒在一起了!

UDP 用户数据报协议    

粘包 仅发生在TCP协议中   

1. 发送端 发送的数据量小 并且间隔短 会粘

2. 接收端 一次性读取了两次数据的内容    会粘 
3. 接收端 没有接收完整  剩余的内容 和下次发送的粘在一起

无论是那种情况,其根本原因在于  接收端不知道数据到底有多少 

代码

技术分享图片
import socket

server = socket.socket()

server.bind((127.0.0.1,8080))
server.listen(5)

conn ,addr = server.accept()
data = conn.recv(1024)
print(data)
data = conn.recv(10)
print(data)
data = conn.recv(7)
print(data)
data = conn.recv(20)
print(data)
        
服务器
技术分享图片
import socket

client = socket.socket()
client.connect((127.0.0.1,8080))
client.send(bstrawberry)
client.send(bberries)
client.send(binterconnection)
客户端
# TCP特点
# 会将数据量比较小的并且时间间隔比较短的数据
# 不知到对方要传的数据有多大
# 将数剧打包成固定长度 发送给对方

例子:

技术分享图片
import socket

import subprocess

server = socket.socket()
server.bind((127.0.0.1,8080))
server.listen(5)

# 敲入命令行拟cmd实行命令
while True:
    conn,addr = server.accept()
    while True:
        try:
            cmd = conn.recv(1024)
            if not len(cmd):
                break
            cmd = cmd.decode(utf-8)
            obj = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
            res = obj.stdout.read() + obj.stderr.read()
            print(len(res))
            conn.send(res)
        except ConnectionResetError as a:
            print(a)
            break
    conn.close()
服务端
技术分享图片
import socket
client = socket.socket()
client.connect((127.0.0.1,8080))
while True:
    cmd = input(>>>).encode(utf-8)
    if not len(cmd):
        continue
    client.send(cmd)
    data = client.recv(1024)
    print(data.decode(gbk))
客户端

 

解决粘包问题
	服务端
		1.先制作一个发送给客户端的字典
		2.制作字典的报头
		3.发送字典的报头
		4.发送字典
		5.再发真实数据
	
	客户端
		1.先接受字典的报头
		2.解析拿到字典的数据长度
		3.接受字典
		4.从字典中获取真实数据的长度
		5.接受真实数据
		

如:

技术分享图片
import socket
import struct
import json
import subprocess

server = socket.socket()
server.bind((127.0.0.1,8080))
server.listen(5)

while True:
    conn,addr = server.accept()
    while True:
        try:
            cmd = conn.recv(1024)
            if not len(cmd):
                break
            cmd = cmd.decode(utf-8)
            obj = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
            res = obj.stdout.read() + obj.stderr.read()
            # 一个文件的报头
            d = {name:baobo,file_size:len(res),info:asdfghjwertyuwertzxcvbnmdfghjkejhk}
            json_d = json.dumps(d)
    #         1.先制作一个字典的报头
            header = struct.pack(i,len(json_d))
    #         2.发送报头长度
            conn.send(header)
    #         3.发送字典
            conn.send(json_d.encode(utf-8))
    #         4.在发送真实数据
            conn.send(res)
        except ConnectionResetError as a:
            print(a)
            break
    conn.close()
服务端

 

技术分享图片
import socket
import struct
import json


client = socket.socket()
client.connect((127.0.0.1,8080))

while True:
    cmd = input(>>>).encode(utf-8)
    if not len(cmd):
        continue
    client.send(cmd)
#     1.先接受字典报头
    header_dict = client.recv(4)
    # 2.解析报头 获取字典的长度
    dict_size = struct.unpack(i,header_dict)[0]
#     3.接收字典数据
    dict_bytes = client.recv(dict_size)
    dict_json = json.loads(dict_bytes.decode(utf-8))
#     4.从字典中获取信息
    print(dict_json)
    recv_size = 0
    real_data = b‘‘
    while recv_size < dict_json.get(file_size):
        data = client.recv(1024)
        real_data += data
        recv_size += len(data)
    print(real_data.decode(gbk))
客户端

 

struct模块

 struct pack//unpack
python中的struct主要是用来处理C结构数据的,读入时先转换为Python的字符串类型,然后再转换为Python的结构化类型,比如元组(tuple)啥的~。一般输入的渠道来源于文件或者网络的二进制流。
struct.pack()和struct.unpack()
在转化过程中,主要用到了一个格式化字符串(format strings),用来规定转化的方法和格式。
struct.pack(fmt,v1,v2,.....)
将v1,v2等参数的值进行一层包装,包装的方法由fmt指定。被包装的参数必须严格符合fmt。最后返回一个包装后的字符串。
struct.unpack(fmt,string)
解包。比如pack打包,然后就可以用unpack解包了。返回一个由解包数据(string)得到的一个元组(tuple), 即使仅有一个数据也会被解包成元组。

 

d28 scoket套接字 struct模块

原文:https://www.cnblogs.com/komorebi/p/11318329.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!