python中的网络编程

1.网络编程基础

1.1OSI7层模型
物理层、数据链路层、网络层、传输层、会话层、表示层、应用层
1.2OSI5层模型
物理层、数据链路层、网络层、传输层、应用层
1.3传输层的协议
tcp协议:可靠的面向连接的全双工通信
udp协议:不可靠的无连接的通信
1.4网络层的协议
ipv4/ipv6协议
1.5数据链路层的协议
arp协议:地址解析协议,通过ip地址找mac地址。
1.6.三次握手和四次挥手(tcp协议)
三次握手
客户端向服务端发送syn信号
服务端接收syn信号并返回ack信号,同时发送syn信号
客户端接收syn信号并返回ack信号
四次挥手
客户端想服务端发送fin信号
服务端接收fin信号并返回ack信号
服务端发送完数据后向客户端发送fin信号
客户端接收fin信号并返回ack信号

2.socket模块

2.1最基础的客户端/服务端代码
服务端

import socket

sk = socket.socket()            #类的实例化#创建一个sever端对象
sk.bind(('127.0.0.1',9000))     #元祖#给sever绑定一个地址和端口
sk.listen()                     #开始监听
conn,add = sk.accept()          #建立连接

conn.send(b'hello')
msg = conn.recv(1024).decode('utf-8')
print(msg)
conn.close()                    #关闭连接

sk.close()                      #关闭服务

客户端

import socket

sk = socket.socket()            #创建一个客户端对象
sk.connect(('127.0.0.1',9000))  #连接服务端

msg = sk.recv(1024).decode('utf-8')
print(msg)
sk.send(b'byebye')
sk.close()                      #关闭连接

2.2多人多次交互的服务端/客户端代码
服务端

import socket

sk = socket.socket()
sk.bind(('127.0.0.1',9000))
sk.listen()
while True:
    conn,addr = sk.accept()
    while True:
        send_msg = input('>>>')
        if send_msg.upper() == 'Q':
            break
        conn.send(send_msg.encode('utf-8'))
        msg = conn.recv(1024).decode('utf-8')
        if msg.upper() == 'Q':
            break
        print(msg)
    conn.close()
    print('服务端已断开连接')

sk.close()

客户端

import socket

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

while True:
    msg = sk.recv(1024).decode('utf-8')
    if msg.upper() == 'Q':
        break
    print(msg)
    send_msg = input('>>>')
    sk.send(send_msg.encode('utf-8'))
    if send_msg.upper() == 'Q':
        break

print('客户端已断开连接')
sk.close()

3.tcp协议中的粘包问题
3.1什么是粘包?
一次发送多条数据时,如第一次发送hello,第二次发送world
在实际接收时,第一次收到helloworld,第二次收到为空。
3.2为什么会发生粘包?
tcp协议数据传输是没有边界的
3.3如何解决粘包
给数据设置一个边界,通过struct模块,发送一个数据来表示数据长度,该数据固定为4个字节
服务端

import socket
import struct

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

conn,addr = sk.accept()
send_msg = input('>>>')
blen = struct.pack('i',len(send_msg))
send_msg2 = input('>>>')
conn.send(blen)
conn.send(send_msg.encode('utf-8'))
conn.send(send_msg2.encode('utf-8'))

conn.close()
sk.close()

客户端

import socket
import struct

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

blength = sk.recv(4)
length = struct.unpack('i',blength)[0]
msg = sk .recv(length).decode('utf-8')
msg2 = sk .recv(1024).decode('utf-8')
print(msg,msg2)

4.udp协议的代码
服务端

import socket

sk = socket.socket(type=socket.SOCK_DGRAM)
sk.bind(('127.0.0.1',9000))

while True:
    msg,addr = sk.recvfrom(1024)
    print(msg,addr)
    send_msg = input('>>>')
    sk.sendto(send_msg.encode('utf-8'),addr)

客户端

import socket

sk = socket.socket(type=socket.SOCK_DGRAM)
sever = ('127.0.0.1',9000)

while True:
    send_msg = input(">>>")
    sk.sendto(send_msg.encode('utf-8'),sever)
    msg = sk.recvfrom(1024)[0].decode('utf-8')
    print(msg)

5.基于tcp协议的小文件传输
服务端

import socket
import json

sk = socket.socket()
sk.bind(('127.0.0.1',9000))
sk.listen()
conn,addr = sk.accept()

jmsg = conn.recv(1024).decode('utf-8')
filename,filesize = json.loads(jmsg)
with open(filename,mode='wb') as f:
    content = conn.recv(1024)
    f.write(content)
conn.close()

sk.close()

客户端

import socket
import os
import json

sk = socket.socket()
sever = ('127.0.0.1',9000)
sk.connect(sever)

abs_path = r'C:\Users\Administrator\工作\账号密码.txt'
filename = os.path.basename(abs_path)
filesize = os.path.getsize(abs_path)
tup = (filename,filesize)
str_tup = json.dumps(tup)
sk.send(str_tup.encode('utf-8'))

with open(abs_path,mode='rb') as f:
    content = f.read()
    sk.send(content)

sk.close()

6.基于tcp协议的大文件传输(有粘包问题)
服务端

import socket
import struct
import json

sk = socket.socket()
sk.bind(('127.0.0.1',9000))
sk.listen()
conn,addr = sk.accept()

blen = conn.recv(4)
tuplen = struct.unpack('i',blen)[0]
str_tup = conn.recv(tuplen).decode('utf-8')
filename,filesize = json.loads(str_tup)
with open(filename,mode='wb')as f:
    while filesize>0:
        content = conn.recv(1024)
        f.write(content)
        filesize -= len(content)

conn.close()
sk.close()

客户端

import socket
import os
import json
import struct

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

abs_path = r'C:\Users\Administrator\Desktop\测试大文件.zip'
filename = os.path.basename(abs_path)
filesize = os.path.getsize(abs_path)
tup =(filename,filesize)
str_tup = json.dumps(tup)
b_tup = str_tup.encode('utf-8')
blen = struct.pack('i',len(b_tup))
sk.send(blen)
sk.send(b_tup)

with open(abs_path,mode='rb') as f:
    while filesize>0:
        content = f.read(1024)
        sk.send(content)
        filesize -= len(content)

sk.close()

7.处理tcp协议并发客户端请求的服务端
服务端

import socketserver
import time

class Mysever(socketserver.BaseRequestHandler):
    def handle(self):
        conn = self.request
        while True:
            for i in range(100):
                msg = conn.recv(1024).decode('utf-8')
                conn.send(msg.upper().encode('utf-8'))
                print(msg+str(i))
                time.sleep(0.5)

server = socketserver.ThreadingTCPServer(('127.0.0.1',9000),Mysever)
server.serve_forever()

客户端

import socket

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

while True:
    for i in range(100):
        sk.send(b'hello')
        content = sk.recv(1024).decode('utf-8')
        print(content+str(i))

8.未登陆情况下验证客户端的合法性
客户端生成一个随机字符串+密钥通过加密算法加密后,发送给服务端,服务端接收字符串,加上密钥加密后,产生的密文与收到的密文一致,则认为合法。
服务端

import socketserver
import hashlib

secret_key = b'123'
class Mysever(socketserver.BaseRequestHandler):
    def handle(self):
        conn = self.request
        randstr = conn.recv(16)
        msg = conn.recv(1024).decode('utf-8')
        sha = hashlib.sha1(secret_key)
        sha.update(randstr)
        if sha.hexdigest() == msg:
            print('是合法的用户')
        else:
            print('不是合法的用户')
            conn.close()


sever = socketserver.ThreadingTCPServer(('127.0.0.1',9000),Mysever)
sever.serve_forever()

客户端

import socket
import os
import hashlib

secret_key = b'123'
randstr = os.urandom(16)
sha = hashlib.sha1(secret_key)
sha.update(randstr)

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

sk.send(randstr)
sk.send(sha.hexdigest().encode('utf-8'))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值