首页 > 其他 > 详细

Socket(套接字)

时间:2019-08-07 23:30:50      阅读:105      评论:0      收藏:0      [点我收藏+]

Socket 通信

客户端

import socket


client = socket.socket()  # 以默认的TCP协议建立双向通道
client.connect((127.0.0.1, 8080))  # 服务端的ip 和 port

client.send(bhello)  # 向服务端发送信息,二进制格式
data = client.recv(1024)  # 接收服务端传来的信息
print(data)

client.close()  # 关闭服务端

服务端

import socket



server = socket.socket()  # 实例化socket对象,不传参数默认TCP协议
server.bind((127.0.0.1, 8080))  # bind((host, prot)) 绑定端口和协议
server.listen()  #

conn, addr = server.accept()  # 等待接听信息,  conn:双向传输通道  addr:客户端地址
data = conn.recv(1024)  # 将客户端传输过来的内容赋值给data   接受1024个字节数据
print(data)
conn.send(bhello word)  # 向客户端传输内容,只能是二进制格式

conn.close()  # 关闭通道
server.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(1027)
    print(data)

服务端

import socket


‘‘‘
服务端有固定的ip和port,要24小时不间断服务客户端

‘‘‘
server = socket.socket()  # 生成一个对象
server.bind((127.0.0.1, 8080))  # 绑定ip和port
server.listen(5)  # 半连接池

while True:  # 连接循环
    conn, addr = server.accept()  # 当一个客户端断开通道后,等待下一个客户端的连接
    while True:  # 通信循环
        try:
            data = conn.recv(1024)
            print(data)  # mac与linux 客户端异常退出后,服务端并不会报错,会循环打印 b‘‘
            if len(data) == 0:break  # 用户兼容mac与linux
            conn.send(data.upper())  # 将数据大写发送给客户端
        except ConnectionAbortedError:  # 捕捉 客户端异常退出 的错误信息
            break  # 当客户端异常退出后结束通信循环
    conn.close()  # 当客户端异常退出后关闭通道,进入下一次连接循环

 

 

 

struct模块

‘‘‘

struct模块的作用是将数据长度转换成固定长度的内容

‘‘‘
import struct


res = asdfghjkl
print(装包前长度, len(res))  # >>> 装包前长度 9
# 装包 成固定长度为4
res1 = struct.pack(i, len(res))
print(装包后长度, len(res1))  # >>> 装包后长度 4
# 解包
res2 = struct.unpack(i, res1)[0]
print(解包后长度, res2)  # 解包后长度 9





d = {
    name:waller,
    file_size: 33335555555444444446666666,
    s:1
}
print(len(d))  # 字典键值对个数

import json
d_size = json.dumps(d)
print(len(d_size))  # 字典转字符转后的字符个数

# 装包 报头 成固定长度为4
msg1 = struct.pack(i, len(d_size))
print(msg1)  # >>> b‘C\x00\x00\x00‘
print(len(msg1))
# 解包 报头 获得原长度
msg2 = struct.unpack(i, msg1)[0]
print(msg2)

 

 

 

 解决粘包问题

服务端
  1.先制作一个发送给客户端的字典
  2.制作字典的报头
  3.发送字典的报头
  4.发送字典
  5.再发真实数据

客户端
  1.先接受字典的报头
  2.解析拿到字典的数据长度
  3.接受字典
  4.从字典中获取真实数据的长度
  5.接受真实数据

服务端

import socket
import subprocess
import struct
import json


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 len(cmd) == 0: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(res)  # res 是二进制格式
            d = {name:jason,file_size:len(res),info:asdhjkshasdad}
            json_d = json.dumps(d)  # 将字典序列化成字符串,便于编码传输
            # 1.先制作一个字典的报头
            header = struct.pack(i,len(json_d))  # 报头自动被编码成二进制
            print(header)  # >>> b‘<\x00\x00\x00‘
            # 2.发送字典报头
            conn.send(header)
            # 3.发送字典
            conn.send(json_d.encode(utf-8))  # 将字典编码发送
            # 4.再发真实数据
            conn.send(res)
            # conn.send(obj.stdout.read())
            # conn.send(obj.stderr.read())
        except ConnectionResetError as e:
            print(e)
            break
    conn.close()

客户端

import socket
import struct
import json

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)
    # 1.先接受字典报头
    header_dict = client.recv(4)  # 接收的报头是二进制格式
    # 2.解析报头 获取字典的长度
    dict_size = struct.unpack(i,header_dict)[0]  # 解包的时候一定要加上索引0
    print(dict_size)
    # 3.接收字典数据
    dict_bytes = client.recv(dict_size)  # 按照字典的长度接收字典
    dict_json = json.loads(dict_bytes.decode(utf-8))  # 将字典反序列化并解码出来
    print(dict_json)
    # 4.从字典中获取信息
    recv_size = 0
    real_data = b‘‘  # 初始化二进制
    while recv_size < dict_json.get(file_size):  # dict_json.get(‘file_size‘) = len(res)
        data = client.recv(1024)   # 接收1024个字节
        real_data += data  # 每读取一次二进制数据拼接一次
        recv_size += len(data)  # 每次读取的长度相加,当总长度和len(res)向同时,结束
    print(real_data.decode(gbk))  # 将读取的二进制数据解码出来

 

Socket(套接字)

原文:https://www.cnblogs.com/waller/p/11318306.html

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