网络编程

网络编程

1.信息传递

 

两个运行总的程序如何传递信息

答:通过文件

2.两台机器上的连个运行中的程序如何通信?

答:通过网络

 

2..网络应用开发构架

 

1.框架的初解    C\S   与B\S

C\S   :C表示client  客户端    S表示  sever 客户端

属于C\S的基本应用场景:输入法 百度云 pycharm git VNC 红蜘蛛

B/S    :B表示browser  浏览器   S表示  sever 客户端

属于B\S的基本应用场景:淘宝 邮箱 百度 博客园 知乎 豆瓣 抽屉

小结:B/S和C/S架构的关系:B/S可以说是特殊的C/S架构

 

2.通信

通信软件与硬件解析:

网卡 :是一个实际存在在计算机中的硬件

mac地址:每一块网卡上都有一个全球唯一的mac地址

交换机:是连接多态机器并帮助通讯的物理设备,只认识mac地址

协议:两台物理设备之间对于要发送的内容,长度,顺序的一些约定

ip地址:

         1.ipv4协议 位的点分十进制 32位2进制表示——————————>0.0.0.0 - 255.255.255.255

          2.ipv6协议 6位的冒分十六进制 128位2进制表示————————>0:0:0:0:0:0-FFFF:FFFF:FFFF:FFFF:FFFF:FFFF

公网ip   :每一个ip地址要想被所有人访问到,那么这个ip地址必须是自己申请的

内网ip:192.172.0.0 - 192.172.255.255

               172.16.0.0 - 172.31.255.255

                10.0.0.0 - 10.255.255.255

arp协议:通过ip地址获取一台机器的mac地址

子网掩码:判断两台机器是否在同一个网段内的

port端口:ip 地址能够确认一台机器

                 范围: 0-65535

ip + port 确认一台机器上的一个应用

 

3. osi  七层模型

 

osi七层协议 协议 设备
应用层 HTTP FTP TFTP SMTP SNMP DNS TELNET HTTPS POP3 DHCP 网络服务与最终用户的一个接口。
表示层 JPEG、ASCll、DECOIC、加密格式等 数据的表示、安全、压缩。(在五层模型里面已经合并到了应用层)
会话层 对应主机进程,指本地主机与远程主机正在进行的会话 建立、管理、终止会话。(在五层模型里面已经合并到了应用层)
传输层 TCP UDP 四层交换机、四层路由器
网络层 ICMP IGMP IP(IPV4 IPV6) ARP RARP 路由器、三层交换机
数据链路层 MAC地址 网卡、交换机
物理层 TCP/IP 层级模型结构 建立、维护、断开物理连接。(由底层网络定义协议

 

 

3.socket (套接字)

python socket模块 完成socket的功能
        工作在应用层和传输层之间的抽象层
        帮助我们完成了所有信息的组织和拼接
sokcet是网络操作的底层了
socket历史:
         同一台机器上的两个服务之间的通信的
基于文件:
        基于网路的多台机器之间的多个服务通信

 

4.tcp协议  与udp  协议

tcp协议和udp协议的特点:

tcp

答:一个面向连接的,流式的,可靠的,慢的,全双工通信
 应用场景:邮件 文件 http web

udp
答:一个面向数据报的,无连接的,不可靠,快的,能完成一对一、一对多、多对一、多对多的高效通讯协议
 应用场景 : 即时聊天工具 视频的在线观看

 

tcp协议:

             

建立连接的时候 : 三次握手
断开连接的时候 : 四次挥手

 

tcp 基本代码格式:

服务端端

import socket
sk = socket.socket()
sk.bind(('127.0.0.1',8898))  #把地址绑定到套接字
sk.listen()          #监听链接
conn,addr = sk.accept() #接受客户端链接
ret = conn.recv(1024)  #接收客户端信息
print(ret)       #打印客户端信息
conn.send(b'hi')        #向客户端发送信息
conn.close()       #关闭客户端套接字
sk.close()        #关闭服务器套接字(可选)

 

客户端

import socket
sk = socket.socket()           # 创建客户套接字
sk.connect(('127.0.0.1',8898))    # 尝试连接服务器
sk.send(b'hello!')
ret = sk.recv(1024)         # 对话(发送/接收)
print(ret)
sk.close()            # 关闭客户套接字

  

udp代码:

sever端

import socket 
udp_sk = socket.socket(type=socket.SOCK_DGRAM)   #创建一个服务器的套接字
udp_sk.bind(('127.0.0.1',9000))        #绑定服务器套接字
msg,addr = udp_sk.recvfrom(1024)
print(msg)
udp_sk.sendto(b'hi',addr)                 # 对话(接收与发送)
udp_sk.close()                         # 关闭服务器套接字

client 端

import socket
ip_port=('127.0.0.1',9000)
udp_sk=socket.socket(type=socket.SOCK_DGRAM)
udp_sk.sendto(b'hello',ip_port)
back_msg,addr=udp_sk.recvfrom(1024)
print(back_msg.decode('utf-8'),addr)

 

 

 

5.粘包

1.概念

同时执行多条命令之后,得到的结果很可能只有一部分,在执行其他命令的时候又接收到之前执行的另外一部分结果,这种显现就是黏包.

tcp协议的粘包现象 :

2. 什么是粘包现象?

发生在发送端的粘包

1.由于两个数据的发送时间间隔短+数据的长度小

2. 所以由tcp协议的优化机制将两条信息作为一条信息发送出去了

3.为了减少tcp协议中的“确认收到”的网络延迟时间

3.发生在接收端的粘包 :

1.由于tcp协议中所传输的数据无边界,所以来不及接收的多条

2.数据会在接收放的内核的缓存端黏在一起

本质: 接收信息的边界不清晰

4.. 解决粘包问题

自定义协议1 首先发送报头 报头长度4个字节 内容是 即将发送的报文的字节长度 struct模块 pack 能够把所有的数字都固定的转换成4字节 再发送报文 自定义协议2 我们专门用来做文件发送的协议 先发送报头字典的字节长度 再发送字典(字典中包含文件的名字、大小。。。) 再发送文件的内容

 

5.简单的解决粘包代码

server端

import os
import socket
sk =sk.socket.socket()
sk.bind(("127.0.0.1",9000))
sk.listen()

conn,addr = sk.accept() num = conn.recv(4)###接收4字节 num = struct.unpack('i',num)[0]###通过接收的4个字节得到文件名长度 file_name = conn.recv(num).decode('utf-8')###知道了文件名 file_size = conn.recv(4)###再接收4字节 filesize = struct.unpack('i',file_size)[0]###得到了文件内容大小 with open(file_name,'wb') as f:###根据文件名打开文件 conntent = conn.recv(filesize)###按照文件内容的大小接收文件的内容 f.write(content)###按照手上来的文件内容写文件 conn.close() sk.close()

client 端

import os
import socket
import struct
sk = socket.socket()
sk.connect(('127.0.0.1',9001))

filename = input('请输入文件路径:')###输入文件名
filename = os.path.basename(filepath)###从文件路径中获取文件名
name_len = struck.pack('i',len(filename))###把长度变成4字节
sk.send(name_len)###发送文件名长度
sk.send(filename.encode('utf-8'))###发送文件名
filesize = os.path.getsize(filepath)###算出文件大小
file_len = struct.pack('i',filesize)###把文件大小变成4字节
sk.send(file_len)###发送文件大小
with open(filepath,'rb') as f:
    content = f.read()###读出文件内容
    sk.send(content)###发送文件内容

sk.close()

 

 

 

5.socketsever模块

server端
import socketsever

class Myserver(socketserver.BaseRequestHandler):
    def handle(self):
        msg =self.request.recv(1024).decode("utf-8")
        self.request.send("1".encode("utf-8"))
        msg =self.request.recv(1024).decode("utf-8")
        self.request.send("1".encode("utf-8"))
        msg =self.request.recv(1024).decode("utf-8")
        self.request.send("1".encode("utf-8"))
server = socketserver.ThreadingTCPserver(("127.0.0.1"),Myserver)
server.serve_forever()
client端
import socket
import time
sk = socket.socket()
sk.connect(("127.0.0.1",9000))
for i in range(3):
    sk.send(b"hello,yuan")
    msg =sk.recv(1024)
    print(msg)
    time.sleep(1)
sk.close() 

 

 

6.非阻塞IO模型

server端
import socket
sk = socket.socket()
sk.bind(("127.0.0.1,9000"))
sk.setblocking(False)
sk.listen()

conn_1=[]
del_1 =[]
while True:
    try:
        conn,addr =sk.accept()
        print(conn)
        conn_1.append(conn)
    except BlockingIOError:
        for c in conn_1:
            try:
                msg =c.recv(1024).decode("utf-8")
                if not msg:
                    del_1.append(c)
                    continue
                print("-->",[msg])
                c.send(msg.upper().encode("utf-8"))
            except BlockingIOError:pass
        for c in del_1:
            conn_1.remove(c)
        del_1.clear()
sk.close()  
client端
import  time
import socket
sk = socket.spcket()
sk.connect(("127.0.0.1",9000))
for i in range(30):
    sk.send(b"wusirt")
    msg =sk.recv(1024)
    print(msg)
    time.sleep(0.2)
sk.close()

 

 

 

7.验证客户端的合法性

 

 

server端
import os 
import hashlib
import socket

def get_md5(secret_key,randseq):
    md5 =hashlib.md5(secret_key)
    md5.update(randseq)
    res =md5.hexdigest()
    return res
def chat(conn):
    while True:
        msg =conn.recv(1024).decode("utf-8")
        print(msg)
        conn.send(msg.upper().encode("utf-8"))
sk = socket.socket()
sk.bind(("127.0.0.1",9000))
sk.listen()

secret_key =b"zalexb"
while True:
    conn,addr =sk.accept()
    randseq =os.urandom(32)
    conn.send(randseq)
    md5code =get_md5(secret_key,randseq)
    ret = conn.recv(32).decode("utf-8")
    print(ret)
    if ret == md5code:
        print("是合法的客户端")
        chat(conn)
    else:
        print("不是合法的客户端")
        conn.close()
sk.clsoe()
client端
import  hashilib
import socket
import time

def get_md5(secret_key,randseq):
    md5 =hashlib.md5(secret_key)
    md5.update(randseq)
    res =md5.hexdigest()
    return res

def chat(sk):
    while True:
        sk.send(b'hello')
        msg = sk.recv(1024).decode('utf-8')
        print(msg)
        time.sleep(0.5)
sk = socket.socket()
sk.connect(('127.0.0.1',9000))

secret_key = b'alexsb'
randseq = sk.recv(32)
md5code = get_md5(secret_key,randseq)

sk.send(md5code.encode('utf-8'))
chat(sk)

sk.close()

 

posted @ 2019-05-25 17:36  三枫博客  阅读(129)  评论(0编辑  收藏  举报