网络编程

时间:2019-04-12
本文章向大家介绍网络编程,主要包括网络编程使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
# web程序两种架构完成的:
# C/S :client(客户端) server(服务端)
# B/S :browser(浏览器) server(服务端)

# 安装一个客户端,然后这个客户端就可以和服务端进行网络交互

# 所有能够用网页访问的网站 这个网站是B/S架构的
# 拉钩 淘宝 12306 京东 51cto 399
# chrome IE 360 火狐 百度 uc sogou

# B/S和C/S架构的关系
# 所有的B/S架构都需要一个浏览器才能访问
# 浏览器是一个软件,相当于一个客户端
# 所有的B/S架构也都是C/S架构的
# 浏览器(browser)是特殊的客户端(client)
# client(broser) <---> server

# 这两种架构哪个好
# C/S 装好之后直接双击就可以使用了
# B/S 极大的简化了我们使用软件的成本

# B/S
# 更符合现在的使用理念
# 但是还有很多功能没有实现
# 在PC端统一了程序的入口

# 在手机端没有那么喜欢用浏览器
# 统一入口的软件


# 你是谁 我是谁
# mac地址 唯一标识了一台机器
# mac地址 说的话 你的mac地址
# 8C-EC-4B-80-AA-4D


# 多台机器之间的通信
# mac : 机器的唯一标识
# 网卡 : 一个计算机上的硬件 这个硬件出厂的时候就被分配了一个mac地址
# ip地址 :比mac好记,能够按照区域来区分(区分你在哪一个局域网内)
# 协议 : 在传输过程中规定位数 顺序等等传输规则的内容
# 交换机 : 局域网内多台机器之间的通信
# arp协议 :通过ip地址找到mac地址
# 局域网概念
# 路由器 : 能够做局域网与局域网之间的通信
# 网关ip : 在一台机器对局域网外的地址进行访问的时候使用的出口ip
# 端口 : 帮助我们找机器上的对应服务 0-65535 惯用的端口号 80,8000之后

# qq ---> qq
# wechat ---> wechat
# web ---> web

# 子网掩码
# 192.168.16.13
# 255.255.0.0
# 11000000.10101000.00010000.00001101
# 11111111.11111111.00000000.00000000
# 11000000.10101000.00010000.00000000 = 192.168.0.0

# 1&1=1
# 1&0 0&0 0&1 =0

# 1&0 = 0
# 1&1 = 1
# 0&0 = 0
# 0&1 = 0

# 192.168.32.5
# 255.255.0.0

# 11000000.10101000.00100000.00000101
# 11111111.11111111.00000000.00000000
# 192.168.0.0



# ip的保留字段
#

# 0.0.0.0-255.255.255.255
# 10.0.0.0-10.255.255.255
# 172.16.0.0-172.31.255.255
# 192.168.0.0-192.168.255.255

# 127.0.0.1 本地的回环地址 别的人找不到你 只有你自己这台机器能找到你自己
# 0.0.0.0 全网段地址


# server : 0.0.0.0:9000

# osi七层协议 七层协议 :每层对应的协议\物理设备
# tcp协议 udp


# ip port
# socket套接字
# 所有的网络通信的底层都是基于socket做的

# socket模块
# TCP协议
# 面向连接\可靠\慢\对传递的数据的长短没有要求
# 两台机器之间要想传递信息必须先建立连接
# 之后在有了连接的基础上,进行信息的传递
# 可靠 : 数据不会丢失 不会重复被接收
# 慢 : 每一次发送的数据还要等待结果
# 三次握手和四次挥手

# UDP协议
# 无连接\不可靠\快\不能传输过长的数据0
# 机器之间传递信息不需要建立连接 直接发就行
# 不可靠 : 数据有可能丢失

# udp协议 即时通讯类的软件 :qq 微信 飞信 歪歪
# tcp协议 发邮件\文件的时候


# osi七层协议
# 应用层
# 表示层
# 会话层
# 传输层
# 网络层
# 数据链路层
# 物理层

# 应用层 python send(b'hello,world')
# socket
# 传输层 端口 tcp/udp协议 四层路由器 四层交换机
# 网络层 ip地址相关 ip协议 路由器 三层交换机
# 数据链路层 mac地址相关 arp协议 网卡 二层交换机
# 物理层 网线

tcp:可靠的,面向连接,传输效率低   

使用TCP的应用:Web浏览器;电子邮件、文件传输程序
udp:不可靠,无连接,传输效率高

使用UDP的应用:域名系统 (DNS);视频流;IP语音(VoIP)

基于UDP协议的socket,简单应用聊天

import socket
ip_port=('127.0.0.1',8081)
udp_server_sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
udp_server_sock.bind(ip_port)

while True:
    qq_msg,addr=udp_server_sock.recvfrom(1024)
    print('来自[%s:%s]的一条消息:\033[1;44m%s\033[0m' %(addr[0],addr[1],qq_msg.decode('utf-8')))
    back_msg=input('回复消息: ').strip()

    udp_server_sock.sendto(back_msg.encode('utf-8'),addr)
import socket
BUFSIZE=1024
udp_client_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

qq_name_dic={
    '金老板':('127.0.0.1',8081),
    '哪吒':('127.0.0.1',8081),
    'egg':('127.0.0.1',8081),
    'yuan':('127.0.0.1',8081),
}


while True:
    qq_name=input('请选择聊天对象: ').strip()
    while True:
        msg=input('请输入消息,回车发送,输入q结束和他的聊天: ').strip()
        if msg == 'q':break
        if not msg or not qq_name or qq_name not in qq_name_dic:continue
        udp_client_socket.sendto(msg.encode('utf-8'),qq_name_dic[qq_name])

        back_msg,addr=udp_client_socket.recvfrom(BUFSIZE)
        print('来自[%s:%s]的一条消息:\033[1;44m%s\033[0m' %(addr[0],addr[1],back_msg.decode('utf-8')))

udp_client_socket.close()
# 1. 黏包现象  发送的两条数据粘在一起了
# 2. 成因 :
# 发送端粘 : 合包机制
# 接收端粘 : 接收不及时
# 数据与数据之间是无边界的流式传输
# 3.解决黏包现象
# 自定义协议
# struct模块
# 把任意长度的数字变成固定的4个字节
# 低级
# 先发送数据的长度
# 再发送数据
import struct
import socket

sk = socket.socket()
sk.bind(('127.0.0.1',9001))
sk.listen()

conn,addr = sk.accept()
str_msg = 'hello,你好么'
byets_msg = str_msg.encode('utf-8')
num = len(byets_msg)
len_bytes = struct.pack('i',num)
conn.send(len_bytes)
conn.send(byets_msg)
conn.send(b'world')
conn.close()

sk.close()
View Code
import time
import struct
import socket

sk = socket.socket()
sk.connect(('127.0.0.1',9001))

time.sleep(0.1)
num= sk.recv(4)
num = struct.unpack('i',num)[0]
msg2 = sk.recv(num)
print(msg2.decode('utf-8'))
print(sk.recv(1024))

sk.close()
View Code
       
# 高级
# 先把所有想发送的数据信息放在字典里
# 发送字典的长度
# 发送字典
# 发送涉及的数据
import json
import struct
import socket

sk = socket.socket()
sk.bind(('127.0.0.1',9001))
sk.listen()

conn,addr = sk.accept()
num = conn.recv(4)
num = struct.unpack('i',num)[0]
str_dic = conn.recv(num).decode('utf-8')
dic = json.loads(str_dic)
with open(dic['filename'],'wb') as f:
    content = conn.recv(dic['filesize'])
    f.write(content)

conn.close()
sk.close()
View Code
import os
import json
import struct
import socket

sk=socket.socket()
sk.connect(('127.0.0.1',9001))

filepath=input('请输入文件路径:')
filename=os.path.basename(filepath)
filesize=os.path.getsize(filepath)
dic={'filename':filename,'filesize':filesize}
str_dic=json.dumps(dic)
bytes_dic=str_dic.encode('utf-8')
View Code
    # osi五层协议
# tcp协议和udp协议
# tcp协议 三次握手 四次挥手
# 代码
# 区别
# tcp 面向连接,流式传输,慢,可靠,全双工
# udp 面向数据包,快,不可靠,无连接
# tcp协议 黏包
# 自定义协议来解决问题 struct
# 为什么会发生黏包
#********* tcp协议能够处理多个client的请求 - socketserver 默写记
import time
import socketserver

class Myserver(socketserver.BaseRequestHandler):
    def handle(self):
        conn = self.request
        for i in range(200):
            conn.send(('hello%s'%i).encode('utf-8'))
            print(conn.recv(1024))
            time.sleep(0.5)


server = socketserver.ThreadingTCPServer(('127.0.0.1',9001),Myserver)
server.serve_forever()
View Code
import socket

sk = socket.socket()
sk.connect(('127.0.0.1',9001))
while True:
    msg = sk.recv(1024)
    print(msg)
    sk.send(b'byebye')
sk.close()
View Code
import socket

sk = socket.socket()
sk.connect(('127.0.0.1',9001))
while True:
    msg = sk.recv(1024)
    print(msg)
    sk.send(b'byebye')
sk.close()
View Code


# 验证客户端合法性 hmac/hashilib(代码示下))
为什么要验证合法性?

# 不是一个面向用户的 需要用户自己输入用户名和密码的
# 而是面向一台server的所有的(500台)客户端
# 都以一种我们共同的方式来进行一个验证

import os
import hmac
import socket

secret_key = b'alex sb'
#os.urandom(32) 给每一客户端发送一个随机的字符串,来保证即使数据被拦截你也不能使用这个消息
sk = socket.socket()
sk.bind(('127.0.0.1',9001))
sk.listen()

conn,addr = sk.accept()
rand = os.urandom(32)
conn.send(rand)

hmac = hmac.new(secret_key,rand)
res = hmac.digest()

ret = conn.recv(1024)
if ret == res:
    print('是合法的客户端')
else:
    print('不是合法的客户端')
    conn.close()
View Code
import hmac
import socket


secret_key = b'alex sb'
sk = socket.socket()
sk.connect(('127.0.0.1',9001))

rand = sk.recv(32)

hmac = hmac.new(secret_key,rand)
res = hmac.digest()

sk.send(res)

sk.close()
View Code