一文搞懂:【Day29】Soket编程

简介: 一文搞懂:【Day29】Soket编程

客户端/服务器架构


    1、什么是客户端服务器/服务器架构??


    服务器:意义--就是一系列软硬件的结合,为一个或多个客户端提供服务。目的:接受请求并响应,然后处理更多请求。


    客户端:发送请求,并接收信息,最后关闭他们之间的事务。


osi七层协议


    1、互联网层的协议分为osi七层tcp/ip五层或四层


每层运行常见物理设备


什么是网络?


    网络是底层的物理链接介质


2.1 物理层


    物理层功能:主要是基于电器特性发送高低电压(电信号),高电压对应数字1,低电压对应数字0


2.2数据链路层


    其功能:定义了电信号的分组方式


    以太网协议(ethernet)规定:


       每一组数据包含head/data ,


        head(18个字节):源地址6个,目标地址6个,数据类型6个


        data(最小46,最大1500):数据包的具体内容


      head + data 最大长度1518,最短长度64,超过长度分片发送


  mac地址:每个电脑都有唯一的mac地址且与ip地址绑定


  广播:有了mac地址,两台电脑可以通过arp协议进行通信,


  enternet 采用广播方式通信,即基本靠吼


2.3 网络层


    1、网络层的意义:用来区分不同的广播域/子网,即网络地址


    2、规定网络地址的协议成为ip协议


    一、ip地址分为:网络部分-->标识子网,主机部分--->标识主机


      注意:单纯的ip地址段只是标识了ip地址的种类,从网络部分或主机部分都无法辨识一个ip所处的子网


      例:172.16.10.1与172.16.10.2并不能确定二者处于同一子网


    二、子网掩码(ip网络部分):


      所谓”子网掩码”,就是表示子网络特征的一个参数。它在形式上等同于IP地址,也是一个32位二进制数字,它的网络部分全部为1,      主机部分全部为0。比如,IP地址172.16.10.1,如果已知网络部分是前24位,主机部分是后8位,那么子网络掩码就是            11111111.11111111.11111111.00000000,写成十进制就是255.255.255.0。


      知道”子网掩码”,我们就能判断,任意两个IP地址是否处在同一个子网络。方法是将两个IP地址与子网掩码分别进行AND运算(两个      数位都为1,运算结果为1,否则为0),然后比较结果是否相同,如果是的话,就表明它们在同一个子网络中,否则就不是。


      比如,已知IP地址172.16.10.1和172.16.10.2的子网掩码都是255.255.255.0,请问它们是否在同一个子网络?两者与子网掩码分别      进行AND运算,


      172.16.10.1:10101100.00010000.00001010.000000001


      255255.255.255.0:11111111.11111111.11111111.00000000


      AND运算得网络地址结果:10101100.00010000.00001010.000000001->172.16.10.0


      172.16.10.2:10101100.00010000.00001010.000000010


      255255.255.255.0:11111111.11111111.11111111.00000000


      AND运算得网络地址结果:10101100.00010000.00001010.000000001->172.16.10.0


      结果都是172.16.10.0,因此它们在同一个子网络。


      总结一下,IP协议的作用主要有两个,一个是为每一台计算机分配IP地址,另一个是确定哪些地址在同一个子网络。


   三、ip数据包


      ip数据包分为head,data部分,无须定义专门的栏目,直接放到以太网的data部分


      ip数据包大小:


          head:长度为20到60字节


          data:最长为65,515字节。


      以太网的数据包最大1500,如果ip数据包超过1500字节,就需要封装成几个以太网数据包分开发送


  四、ARP协议


      arp协议功能:广播的方式发送数据包,获取目标主机的mac地址


   流程:如果两台电脑互相访问(172.168.0.2访问172.168.0.3):首先通过ip地址和子网掩码判断是否在同一子网——>如果在同一子网会以广播的方式在局域网内传播,---->如果不在同一子网会通过 数据包中的目标ip地址 和ARP协议获取网关的mac地址---然后在再子网内进行广播的方式发送,主机拆开包后,发现ip地址是自己的,就响应返回自己的mac地址


2.4 传输层  


    1.传输层的由来:网络层的ip帮我们区分子网,以太网层的mac帮我们找到主机,端口找到应用程序,端口即应用程序与网卡关联的编      号。


    2.传输层功能:建立端口到端口的通信


    3.ip 加mac + 端口 :标识唯一的软件


    4.可靠传输,TCP数据包没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常TCP数据包的长度不会超过IP数据包的长      度,以确保单个TCP数据包不必再分割。


2.5应用层


    应用层由来:使用的程序都是应用层,各种应用程序规定好数据的组织形式


    应用层的功能:规定应用层数据的格式


soket


    1.socket 是什么:soket 是应用层与Tcp/ip 通信的中间软件抽象层,他是一组接口


    socket:绑定地址的时候,网端必须是整数,最好大于1024 ,小于65535


    socket :进行传送时都是使用bytes类型


#服务端


import socket


import time


my_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)


my_server.bind(('127.0.0.1',8080))


my_server.listen(5)


tcp_sock, addr = my_server.accept()


res1 = tcp_sock.recv(1)


res2 = tcp_sock.recv(4)


print(res1) print(res2)


#客户端


import socket


import time


client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)


client.connect(('127.0.0.1', 8080))


client.send(bytes('hello','utf-8'))


time.sleep(1)


client.send(bytes('world','utf-8'))


以上两段代码:服务端的输出结果,


#服务端


b'h'


b'ello'


原因为:客户端,发送完第一条信息(‘hello’)后,中间滞留一秒的时间。此时,这条信息已经通过tcp/ip协议传输到服务端电脑,服务端socket通过os.模块从内存中加读取刚刚传送过来的信息,由于服务端第一次只接收一个字节的信息,剩余的字节还停留在内存中,到了第二次接收的时候,才把内存中的信息读取完。


如何解决粘包问题


#客户端


import socket


import json


import subprocess


import struct


sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)


sock_server.bind(('127.0.0.1',8080))


sock_server.listen(5)


while True:


conn, adrr = sock_server.accept()


while True:


try:


cmd_data = conn.recv(1024)


print(cmd_data)


if not cmd_data: break


cmd_data = cmd_data.decode("utf-8")


sub_data = subprocess.Popen(cmd_data, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)


cmd_data_stdout = sub_data.stdout.read()


cmd_data_stderr = sub_data.stderr.read()


# heard_json = json.dumps(sub_data)


# print(111)


# heard_bytes = bytes(heard_json, 'utf-8')


heard_len = struct.pack('i', len(cmd_data_stdout)+len(cmd_data_stderr))


conn.send(heard_len)


conn.send(cmd_data_stdout+cmd_data_stderr)


except ConnectionError:


break


conn.close()


sock_server.close()


# import socket


import json


import subprocess


import struct


sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)


sock_server.bind(('127.0.0.1',8080))


sock_server.listen(5)


while True:


conn, adrr = sock_server.accept()


while True:


try:


cmd_data = conn.recv(1024)


print(cmd_data)


if not cmd_data: break


cmd_data = cmd_data.decode("utf-8")


sub_data = subprocess.Popen(cmd_data, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)


cmd_data_stdout = sub_data.stdout.read()


cmd_data_stderr = sub_data.stderr.read()


//代码效果参考:http://www.lyjsj.net.cn/wx/art_24253.html

# heard_json = json.dumps(sub_data)

# print(111)


# heard_bytes = bytes(heard_json, 'utf-8')


heard_len = struct.pack('i', len(cmd_data_stdout)+len(cmd_data_stderr))


conn.send(heard_len)


conn.send(cmd_data_stdout+cmd_data_stderr)


except ConnectionError:


break


conn.close()


sock_server.close()


#服务端


import socket


import json


import struct


cline = socket.socket(socket.AF_INET, socket.SOCK_STREAM)


cline.connect(('127.0.0.1', 8080))


while True:


user_input = input("<span style="color: rgba(128, 0, 0, 1)"]]").strip()


if not user_input: continue


cline.send(bytes(user_input,"utf-8"))


server_total = cline.recv(4)


head_total_len = struct.unpack('i', server_total)【0】


print(head_total_len)


ser_how = 0


ser_data = b''


while ser_how [span style="color: rgba(0, 0, 0, 1)"> head_total_len:


data = cline.recv(1024)


ser_how += len(data)


ser_data += data


print(ser_how)


print(ser_data.decode("gbk"))


远程操控 cmd 解决粘包


#服务端


import socket


import json


import struct


import subprocess


import os


import hashlib


servers = socket.socket(socket.AF_INET, socket.SOCK_STREAM)


servers.bind(('127.0.0.1',8080))


servers.listen(5)


def get_func(filename):


md5_hs = hashlib.md5()


heard_total = {'filename':filename,


"len_size":os.path.getsize(r"%s"%filename),


"article_md5": md5_hs.hexdigest()


}


heard_json = json.dumps(heard_total)


heard_bytes = heard_json.encode('utf-8')


heard_size = struct.pack('i',len(heard_bytes))


conn.send(heard_size)


conn.send(heard_bytes)


with open(r"%s"% filename, 'rb')as f:


for lien in f:


md5_hs.update(lien)


conn.send(lien)


while True:


conn, addr = servers.accept()


while True:


try:


data = conn.recv(1024)


if not data:break


data_str = data.decode('utf-8')


print(type(data_str))


cmd, filename = data_str.split()


print(filename)


if cmd == 'get':


get_func(filename)


except ConnectionError:


break


#客户端


import socket


import struct


import json


import hashlib


import time


client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)


client.connect(('127.0.0.1',8080))


while True:


user_input = input("<span style="color: rgba(128, 0, 0, 1)"]]").strip()


if not user_input:continue


user_input = user_input.encode("utf-8")


client.send(user_input)


server_data = client.recv(4)


heard_size = struct.unpack('i',server_data)【0】


heard_bytes = client.recv(heard_size)


heard_json = heard_bytes.decode("utf-8")


heard_dic = json.loads(heard_json)


print(heard_dic)


file_size = heard_dic【'len_size'】


file_name = heard_dic【'filename'】


article_md5 = heard_dic【'article_md5'】


ser_size = 0


hash_obj = hashlib.md5()


print(article_md5)


print(hash_obj.hexdigest())


# while ser_size < file_size:


# time.sleep(0.1)


# char_num = ser_size//file_size


# pre_str = '\r%s%%:%s'%(100,'|'100)if ser_size == file_size else "\r%s%%:%s"%(char_num,"|"char_num)


# print(pre_str, end='', flush=True)


with open(r'E:\资料\day30sokect粘包\to.avi','wb')as f:


while ser_size [span style="color: rgba(0, 0, 0, 1)"> file_size:


data = client.recv(1024)


# print(data)


hash_obj.update(data)


f.write(data)


ser_size += len(data)


远程下载

相关文章
|
7月前
|
机器学习/深度学习 人工智能 运维
10 分钟搞懂 LLMOps
10 分钟搞懂 LLMOps
483 0
|
7月前
|
人工智能 网络协议 算法
5 分钟搞懂 ECN
5 分钟搞懂 ECN
865 0
|
2天前
|
消息中间件 Linux API
一篇文章讲明白LinuxKernel编程
一篇文章讲明白LinuxKernel编程
|
2天前
|
数据可视化 API
一文搞懂:【Havok】
一文搞懂:【Havok】
|
2天前
|
API
一文搞懂:关于串行接口
一文搞懂:关于串行接口
一文搞懂:_.cloneDeep(value)
一文搞懂:_.cloneDeep(value)
|
3天前
|
机器学习/深度学习 定位技术
一文搞懂:【OpenJ_Bailian
一文搞懂:【OpenJ_Bailian
|
3天前
一文搞懂:【华为oj】iNOC产品部
一文搞懂:【华为oj】iNOC产品部
|
3天前
|
PHP
一文搞懂:yeild理解
一文搞懂:yeild理解
|
3天前
|
前端开发 JavaScript
一文搞懂:【Reduc】ReactCounterExample
一文搞懂:【Reduc】ReactCounterExample