第十二章:网络编程

第十二章:网络编程

一、基本概念

"""
一、客户端和服务端架构
C/S架构
    client--------互联网--------server

B/S
    browser--------互联网--------server

服务端:
    1、一直对外提供服务
    2、服务端的必须绑定一个固定的地址
    3、并发能力
    

二、网络通信
互联网存在的意义?
    互联网存在的意义让通信变得方便 =》通信

什么是互联网?
    网络=底层物理连接介质+互联网通信协议

    ip+mac=》标识全世界范围内独一无二的一台计算机
    ip+mac+port=》标识全世界范围内独一无二的一个基于网络通信的应用软件

    因为ARP协议的存在,可以将ip解析成mac,所以:
    ip+port=》标识全世界范围内独一无二的一个基于网络通信的应用软件
    
    
三、OSI七层协议
七层协议:
	1.应用层:OSI 的应用层协议包括文件的传输、访问及管理协议(FTAM) ,以及文件虚拟终端协议(VIP)和公用管理系统信息(CMIP)等
	2.表示层:供多种功能用于应用层数据编码和转化,以确保以一个系统应用层发送的信息 可以被另一个系统应用层识别
	3.会话层:建立、管理和终止表示层与实体之间的通信会话
	4.传输层:向高层提供可靠的端到端的网络数据流服务
	5.网络层:负责在源和终点之间建立连接
	6.数据链接层:通过物理网络链路提供数据传输。不同的数据链路层定义了不同的网络和协 议特征,其中包括物理编址、网络拓扑结构、错误校验、数据帧序列以及流控
	7.物理层:物理层负责最后将信息编码成电流脉冲或其它信号用于网上传输

四、五层协议
	应用层
	传输层
	网络层
	数据链路层
	物理层
	
五、协议:规定数据的组织规格
格式:头部+数据部分

封包裹的过程:数据外加头
拆包裹的过程:拆掉头获取数据
计算机1:                            计算机2:

应用层                               应用层
传输层                               传输层
网络层                               网络层
数据链路层                            数据链路层
物理层  <===========交互机===========> 物理层
                                     0101010101010

(源mac地址,目标mac地址)(源ip地址,目标ip地址)数据
"""

二、socket是什么?

Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。

三、基于TCP的套接字编程

客户端

import socket

#  获取tcp/ip套接字
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  # 流式协议=》tcp

phone.connect(("127.0.0.1",8080))   # ip和port

phone.send("hello".encode('utf-8'))
data=phone.recv(1024)  # 最大接收1024个字节
print(data)

phone.close()

服务端

import socket

# 1、买电话
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  # 流式协议=》tcp
# print(phone)

# 2、插电话卡
phone.bind(("127.0.0.1",8080))

# 3、开机
phone.listen(5)
print("starting:%s:%s" %("127.0.0.1",8080))

# 4、等电话连接
conn,client_addr=phone.accept()
# print(conn,client_addr)
print(client_addr)

# 5、收/发消息
data=conn.recv(1024)  # 最大接收1024个字节
print(data)
conn.send(data.upper())

# 6、挂电话
conn.close()

# 7、关机
phone.close()

四、加上循环的套接字

客户端

import socket

phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  # 流式协议=》tcp

phone.connect(("127.0.0.1",8081))

while True:
    msg=input('>>: ').strip()  # msg=''
    if len(msg) == 0:continue
    phone.send(msg.encode('utf-8'))
    # print('has send=====>')
    data=phone.recv(1024)
    # print('has recv=====>')
    print(data)

phone.close()

服务端

import socket

phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  # 流式协议=》tcp
# phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #就是它,在bind前加
phone.bind(("127.0.0.1",8081))

phone.listen(5)
print("starting:%s:%s" %("127.0.0.1",8081))

# 链接循环
while True:
    conn,client_addr=phone.accept()
    print(client_addr)

    # 通信循环
    while True:
        try:  # 针对windows系统
            data=conn.recv(1024)  # 最大接收1024个字节
            if len(data) == 0:break  # 针对linux系统
            print(data)
            conn.send(data.upper())
        except Exception:
            break
    conn.close()

phone.close()

五、远程执行命令的程序

客户端

import socket

phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  # 流式协议=》tcp

phone.connect(("127.0.0.1",8082))

while True:
    cmd=input('>>: ').strip()  # msg=''
    if len(cmd) == 0:continue
    phone.send(cmd.encode('utf-8'))
    data=phone.recv(1024)
    print(data.decode('gbk'))

phone.close()

服务端

import socket
import subprocess

phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  # 流式协议=》tcp
phone.bind(("127.0.0.1",8082))

phone.listen(5)

# 链接循环
while True:
    conn,client_addr=phone.accept()
    print(client_addr)

    # 通信循环
    while True:
        try:  # 针对windows系统
            cmd=conn.recv(1024)  # 最大接收1024个字节
            if len(cmd) == 0:break  # 针对linux系统
            obj = subprocess.Popen(
                cmd.decode('utf-8'),
                shell=True,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE
            )

            conn.send(obj.stdout.read())
            conn.send(obj.stderr.read())
        except Exception:
            break
    conn.close()

phone.close()

struct模块的应用

import struct

res = struct.pack('i',10241111)
print(res, len(res))

recv_header = struct.unpack('i', res)
print(recv_header[0])

# b'WD\x9c\x00' 4
# 10241111

服务端

import socket
import subprocess
import struct

server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)  # 流式协议=》tcp
# print(server)
server.bind(('127.0.0.1',8080))
server.listen(5)

# 链接循环
while True:
    conn,addr=server.accept()
    print(addr)

    # 通信循环
    while True:
        try:
            cmd=conn.recv(1024)
            if len(cmd) == 0:break  # 针对linux
            obj=subprocess.Popen(cmd.decode('utf-8'),shell=True,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE
                                 )

            stdout_res=obj.stdout.read()
            stderr_res=obj.stderr.read()
            total_size=len(stdout_res) + len(stderr_res)
            print(total_size)

            # 1、先发送数据的总大小
            conn.send(struct.pack('i',total_size))

            # 2、再发送真实的数据
            conn.send(stdout_res)
            conn.send(stderr_res)
        except Exception:  # 针对windows
            break
    conn.close()
server.close()

客户端

import socket
import struct

client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)  # 流式协议=》tcp
client.connect(('127.0.0.1',8080))

while True:
    cmd=input(">>>: ").strip()
    if len(cmd) == 0:continue
    client.send(cmd.encode('utf-8'))
    # 1、先拿到数据的总大小
    header_bytes=client.recv(4)
    header=struct.unpack('i',header_bytes)
    total_size=header[0]

    # 2、再接收数据
    recv_size=0
    res=b''
    while recv_size < total_size:
        data=client.recv(1024)
        recv_size+=len(data)
        res+=data

    print(res.decode('gbk'))

六、解决粘包问题

struct模块的应用

import struct
import json

header_dic={
    
    
    'filenme':"a.txt",
    'md5':"sdfasfdasfdasfd123123213",
    "total_size":999999912343123442802
}

header_json=json.dumps(header_dic)

header_json_bytes=header_json.encode('utf-8')

# print(header_json_bytes)
# print(len(header_json_bytes))

服务端

import socket
import subprocess
import struct
import json

server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)  # 流式协议=》tcp
# print(server)
server.bind(('127.0.0.1',8080))
server.listen(5)

# 链接循环
while True:
    conn,addr=server.accept()
    print(addr)

    # 通信循环
    while True:
        try:
            cmd=conn.recv(1024)
            if len(cmd) == 0:break  # 针对linux
            obj=subprocess.Popen(cmd.decode('utf-8'),shell=True,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE
                                 )

            stdout_res=obj.stdout.read()
            stderr_res=obj.stderr.read()
            total_size=len(stdout_res) + len(stderr_res)
            print(total_size)

            header_dic = {
    
    
                'filenme': "a.txt",
                'md5': "sdfasfdasfdasfd123123213",
                "total_size": total_size
            }
            header_json = json.dumps(header_dic)
            header_json_bytes = header_json.encode('utf-8')

            # 1、先发送报头的长度
            conn.send(struct.pack('i',len(header_json_bytes)))

            # 2、再发送报头
            conn.send(header_json_bytes)

            # 3、然后发送真实的数据
            conn.send(stdout_res)
            conn.send(stderr_res)
        except Exception:  # 针对windows
            break
    conn.close()
server.close()

客户端

import socket
import struct
import json

client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)  # 流式协议=》tcp
client.connect(('127.0.0.1',8080))

while True:
    cmd=input(">>>: ").strip()
    if len(cmd) == 0:continue
    client.send(cmd.encode('utf-8'))

    # 1、先拿到报头的长度
    header_json_bytes_size=struct.unpack('i',client.recv(4))[0]
    # 2、再收报头
    header_json_bytes=client.recv(header_json_bytes_size)
    header_json=header_json_bytes.decode('utf-8')
    header_dic=json.loads(header_json)
    print(header_dic)

    # 3、最后接收数据
    total_size=header_dic['total_size']
    recv_size=0
    res=b''
    while recv_size < total_size:
        data=client.recv(1024)
        recv_size+=len(data)
        res+=data

    print(res.decode('gbk'))

七、基于udp协议的套接字通信

服务端

# import socket
from socket import *
import time

server=socket(AF_INET,SOCK_DGRAM)
server.bind(('127.0.0.1',8080))

while True:
    data,client_addr=server.recvfrom(1024)
    time.sleep(10)
    server.sendto(data.upper(),client_addr)

客户端

# import socket
from socket import *

client = socket(AF_INET, SOCK_DGRAM)

while True:
    msg=input('>>>: ').strip()
    client.sendto(msg.encode('utf-8'),('127.0.0.1',8080))
    data,server_addr=client.recvfrom(1024)
    print(data.decode('utf-8'))

八、socket server模块

(一) TCP协议

服务端

import socketserver

class MyrequestHandler(socketserver.BaseRequestHandler):
    def handle(self):
        # self.request  # conn对象
        print(self.client_address)
        while True:
            try:
                data=self.request.recv(1024)
                if len(data) == 0:break
                self.request.send(data.upper())
            except Exception:
                break
        self.request.close()

if __name__ == '__main__':
    s=socketserver.ThreadingTCPServer(('127.0.0.1',8080),MyrequestHandler)
    s.serve_forever()

客户端

import socket
import struct

client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)  # 流式协议=》tcp
client.connect(('127.0.0.1',8080))

while True:
    cmd=input(">>>: ").strip()
    if len(cmd) == 0:continue
    client.send(cmd.encode('utf-8'))
    data=client.recv(1024)
    print(data.decode('utf-8'))

(二) UDP协议

服务端

import socketserver
import time

class MyrequestHandler(socketserver.BaseRequestHandler):
    def handle(self):
        # self.request  # conn对象
        data=self.request[0]
        self.request[1].sendto(data.upper(),self.client_address)
        time.sleep(10)

if __name__ == '__main__':
    s=socketserver.ThreadingUDPServer(('127.0.0.1',8080),MyrequestHandler)
    s.serve_forever()

客户端

# import socket
from socket import *

client = socket(AF_INET, SOCK_DGRAM)

while True:
    msg=input('>>>: ').strip()
    client.sendto(msg.encode('utf-8'),('127.0.0.1',8080))
    data,server_addr=client.recvfrom(1024)
    print(data.decode('utf-8'))

作者:吴常文
出处:https://blog.csdn.net/qq_41405475
本文版权归作者和CSDN共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

猜你喜欢

转载自blog.csdn.net/qq_41405475/article/details/114988016