第三十天

回顾

tcp协议的多人多次通信

  1. 和一个人通信说多句话
  2. 和一个人聊完在和其他人聊
  3. socket() tcp协议 的server
  4. bind 绑定一个ip 和端口
  5. listen 剪影 代表socket 服务的开启
  6. accept 等 到有客户端来访问和客户端建立连接
  7. send 直接通过连接发送消息 不需要写地址
  8. recv 只接受消息
  9. connect 客户端 tcp 协议 的方法 和server 端建立连接
  10. close 关闭服务\链接

udp协议

socket(type=socket.SOCK_DGRAM)

sendto 需要写一个对方的地址

recvfrom 接收消息和地址

close 关闭服务\链接

没一句话什么意思?执行到哪里程序会阻塞? 为什么阻塞? 什么时候结束阻塞?

  1. input() 等待 指导用户输入enter键

  2. accept() 阻塞 有客户端和我建立连接之后

  3. recv() 阻塞,直到收到对方的消息之后

  4. recvfrom 阻塞 直到收到对方的消息之后

  5. connect 阻塞 直到server 端结束了一个对client的服务 开始和当前的client建立连接的时候

粘包现象

tcp是流式传输,数据和数据之间没有边界

解决粘包现象 :

​ 先发送4字节的数据长度 先接受4字节 知道数据长度

​ 再按照长度发送数据 在按照长度接收数据

今日

tcp协议的自定义协议解决年报问题

验证客户端的合法性

并发的TCP协议 server端 socketserver

udp 转发

服务端

import socket
friend_lst={'alex':'32','太白':'33'}
sk=socket.socket(type=socket.SOCK_DGRAM)

sk.bind(('127.0.0.1',9001))
dic={}
while 1:
    msg,addr=sk.recvfrom(1500)
    msg=msg.decode('utf-8')
    name,message=msg.split('|')
    # print(addr)
    if name not in dic:
     dic[name]=addr
    # print(dic)
    msg='\033[1;%sm %s:%s\033[0m'%(friend_lst.get(name,'30'),name,message)
    # print(msg)
    # content=input('>>>')
    if len(dic)==2:
        if name =='alex':
            sk.sendto(msg.encode('utf-8'),dic['太白'])
        else:
            sk.sendto(msg.encode('utf-8'), dic['alex'])
    # if content.upper()=='Q':break



客户端1

import socket
name='太白'
sk=socket.socket(type=socket.SOCK_DGRAM)


while 1:
    content=input('>>>')
    if content.upper()=='Q':break
    content ="%s|%s" %(name,content)
    sk.sendto(content.encode('utf-8'),('127.0.0.1',9001))
    msg=sk.recv(1024).decode('utf-8')
    # if msg.upper() == 'Q': break
    print(msg)

客户端2

import socket
name='alex'
sk=socket.socket(type=socket.SOCK_DGRAM)


while 1:
    content=input('>>>')
    if content.upper()=='Q':break
    content ="%s|%s" %(name,content)
    sk.sendto(content.encode('utf-8'),('127.0.0.1',9001))
    msg=sk.recv(1024).decode('utf-8')
    # if msg.upper() == 'Q': break
    print(msg)

#
# msg=sk.recv(1024)
# print(msg)
# sk.send(b'bye')
#
# sk.close()

基于tcp协议 收文件第一种 发送小文件 不考虑粘包

服务端

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

conn,_=sk.accept()
msg=conn.recv(1024).decode('utf-8')
msg=json.loads(msg)  #json语句  转换成普通

with open (msg['filename'],'wb') as f:
    content=conn.recv(msg['filesize'])
    print(('->',len(content)))
    f.write(content)

conn.close()
sk.close()

客户端 --发送端

import os
import socket
import json
sk=socket.socket()
sk.connect(('127.0.0.1',9001))
abc_path=r'C:\Users\Administrator\Desktop\小丁变优秀的代码\day31\asdas.py'
filename=os.path.basename(abc_path)
filesize=os.path.getsize(abc_path)
dic={'filename':filename,'filesize':filesize}
str_dic=json.dumps(dic)  # 转换成  json 语句
sk.send(str_dic.encode('utf-8'))

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

sk.close()

基于tcp协议 收文件第一种 发送大文件 要考虑粘包

#接收端

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

conn,_=sk.accept()
msg_len=conn.recv(4)
dic_len=struct.unpack('i',msg_len)[0]   # 收到的解包  是一个元祖 第0 个 才是咱们想要的长度
msg=conn.recv(dic_len).decode('utf-8')
msg=json.loads(msg)  #json语句  转换成普通

with open (msg['filename'],'wb') as f:
    while msg['filesize']>0:
        content=conn.recv(1024)
        msg['filesize']-=len(content)  #每次减去实际收到的字节数  有效解决粘包问题
        f.write(content)

conn.close()
sk.close()

发送端

import os
import socket
import json
import struct
sk=socket.socket()
sk.connect(('127.0.0.1',9001))
abc_path=r'C:\Users\Administrator\Desktop\小丁变优秀的代码\day31\asdas.py'
filename=os.path.basename(abc_path)
filesize=os.path.getsize(abc_path)
dic={'filename':filename,'filesize':filesize}
str_dic=json.dumps(dic)  # 转换成  json 语句
b_dic=str_dic.encode('utf-8')   #先转成 'utf-8'  格式 再进行 struct
mlen=struct.pack('i',len(b_dic))#struct 包  转换成4 字节
sk.send(mlen)  #4个字节    表示字典的转成 字节之后的长度
sk.send(b_dic) # 具体的字典的数据

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



sk.close()

socketserver--处理并发客户端请求 并发

### socket 底层模块         封装度低 效率不固定

### socketserver基于socket完成的    封装度高

tcp协议的server 端处理并发的客户端请求

网盘:文件的 上传与下载

.
#持续发消息,  当一个连接断了以后,  下一个连接再连上的时候  直接继续发消息
# 其实想要实现的是一个并发网络编程  
#用 socket 实现的 是一个基础的模型
#下面开始 使用socketserver 模块 实现

#服务端
import socket
import time
sk= socket.socket()
sk.bind(('127.0.0.1',9001))
sk.listen()


while 1:
    conn, _ = sk.accept()
    while 1:
            try:
                content=conn.recv(1024).decode('utf-8')
                conn.send(content.upper().encode('utf-8'))
                time.sleep(0.5)

            except ConnectionResetError:
                break
                
                
                
#客户端
import socket
sk= socket.socket()
sk.connect(('127.0.0.1',9001))

while 1:
    sk.send(b'hello')
    content= sk.recv(1024).decode('utf-8')
    print(content)

并发 socketserver

# 每一个客户端连上之后 都进入了 handle函数里面了
# 每一个客户端都有一个 handle  互不干扰

$$$$$$$$$$$$$$$$$$$背会$$$$$$$$$$$$$$$$$$$


import time
import socketserver   #******************
class Myserver(socketserver.BaseRequestHandler):  #BaseRequestHandler  #******************
    def handle(self):  #******************
        # print(self.request)
        # < socket.socket
        # fd = 756, family = AddressFamily.AF_INET, type = SocketKind.SOCK_STREAM, proto = 0, laddr = ('127.0.0.1',
        #                                                                                              9001), raddr = (
        #
        #
        conn = self.request
        while 1:
            try:
                content = conn.recv(1024).decode('utf-8')
                conn.send(content.upper().encode('utf-8'))
                time.sleep(0.5)

            except ConnectionResetError:
                break
server=socketserver.ThreadingTCPServer(('127.0.0.1',9001),Myserver)  #ThreadingTCPServer  #******************
server.serve_forever()  #******************

import time
import socketserver
class Myserver(socketserver.BaseRequestHandler):
    def Handel(self):
        conn=self.request
server=socketserver.ThreadingTCPServer(('127.0.0.1',9001),Myserver)
server.serve_forever()


# self.requset  打印
# laddr=('127.0.0.1', 9001), raddr=('127.0.0.1', 13958)>
# 只有自己的地址的  是sk
# 有自己的  也有对方的地址  是 conn



客户端还是和原来一样  
posted @ 2020-03-25 14:05  小丁变优秀  阅读(111)  评论(0)    收藏  举报