网络编程

1.网络通信协议
网络通讯的基本要素
C/S构架
OSI七层模型
2.socket编程


server(服务器) client(客户端)

网络通讯的基本要素
1.物理连接介质 2.通讯协议


应用 表示 会话 传输 网络 数据链路 物理

以太网协议


1.物理层 规定 物理介质的相关规范 比如网线接口是什么样的 有几根线
二进制
问题:无法理解单纯的二进制数据
2.数据链路层 工作在这一层的是以太网协议
规定一组电信号有多少位 规定每组电信号包含什么样的内容
每一台电脑必须拥有一个全球唯一的mac地址(可以有多个)
通过广播的方式 来找到对方的mac地址
255-1 一个局域网的容量
问题:不可能全球广播 会造成广播风暴(广播太多 网络瘫痪)

3.网络层
工作在这一层的是ip协议
网络地址协议:给每一个计算机分配一个ip地址
dns(域名解析服务器) 将域名转为ip地址
ARP协议是根据ip获取对方的mac地址
在IP协议中 包含一个路由协议: 用最短的路径找到对方的主机
路由器就相当于古代的驿站

通常是ipv4
0.0.0.0-255.255.255.255
前三段称之为网络号 后一段称之为主机号
子网掩码用来判断是否处于同一个局域网
arp协议 把ip转成mac地址的协议

ip协议最主要的目的就是找到全球范围内的某一个局域网 与某一台具体的计算机

问题:一个数据包到达对方计算机后 到底交给哪一个应用程序来处理

端口范围0-65535 0-1023为系统占用端口

传输层: 用于规范数据传输方式(tcp udp) 以及识别应用程序(端口号)


四次挥手 断开连接 也是为了确保数据传输完整性

TCP
优点 可靠 保证数据传输是完整的
缺点 由于每次都需要传输确认信息 导致传输效率降低
适用于 对数据完整性要求高的程序 比如支付数据 文字信息等
相当于手机

udp 不可靠传输
优点 由于不需要传输确认信息 所以传输效率高于tcp协议
缺点 传输数据可能不完整 完全不关心对方是否收到数据 把数据发送到网络中
适用于:视频 语音 即时对战游戏
相当于对讲机

网络传输数据 其实就是一层层封包与一层层解包的过程

应用层:主要是用于规定 双防应用程序之间以什么形式来传输数据
这一层的数据形式是由程序员自己来定制的 长剑有HTTP FTP Email等等


重点关注的就是传输层协议 以及网络地址

socket
封装了传输层一堆协议的模块
当你需要开发一款C/S结构的应用程序的时候 就需要使用它
基于C/S结构的应用程序 需要分别开发服务器和客户端程序
学习的重点就是如何使用socket编写服务器程序 以及客户端程序

    通常应该先开发服务器

 

服务器程序的大致流程
1.创建socket对象
2.绑定ip和port
3.监听连接
4.接受请求
5.收发数据
6.断开连接

import socket

#默认情况下创建的是基于网络的TCP协议的socket对象
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#参数1:协议家族 网络的为AF_INET
#参数2:type  用于设置采用的传输协议 TCP的为SOCK_STREAM UDP为SOCK_DGRAM

#重用端口号 当你已经关闭了服务器 但是还是报异常说 端口占用时  可以使用
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

s.bind(('127.0.0.1',8888))
#端口号取值:0-65535 0-1023是系统保留的

s.listen()#监听客户端的连接

#c:当接受到请求时  会返回一个表示客户端的socket对象
#客户端的socket对象就负责这个客户端的数据手法
#c_addr  同时返回对方的ip和端口 打包成元组
c,addr=s.accept()#接受客户端的连接请求

#开始接受数据
#recv接受数据
#buffersize 缓冲区大小  单位为字节 1kb
data=c.recv(1024)
print(data.decode('utf-8'))
c.close()#断开与客户端的连接
s.close()#关闭服务器socket 后续的客户端就无法在连接服务器了  一般正常服务器是不会关闭的
import socket

#创建socket对象
c=socket.socket()

#与服务器建立连接 传入服务器的ip和端口
c.connect(('127.0.0.1',8888))


#收发数据 只能发送bytes类型的数据(任何数据都能发)
c.send('你真帅'.encode('utf-8'))


#断开与服务器的连接
c.close()
import socket
s=socket.socket()
s.bind(('127.0.0.1',8888))
s.listen()



# 连接循环  重复接受客户端连接请求 直到关闭程序为止
while True:
    c,addr=s.accept()
    print('收到了一个请求')
    # 通讯循环 重复的收发数据 直到断开连接
    while True:
        try:
            data=c.recv(1024)# 也是一个阻塞函数 会一直等到对方发送数据为止
            # 如果对方断开了连接  会重复收到空消息
            if not data:
                print('客户端下线了')
                break
            print('收到了一个数据',data)
            # 给客户端 返回一个消息
            data+=b'dsb'
            c.send(data)
        except ConnectionResetError:
            print('对方异常断开连接')
            break

            # s.send(data) #错误示范 服务器只负责 接收请求 建立连接 具体的收发数据由客户端socket来做
            # 注意:服务器和客户端之间 不能同时都执行recv  由于recv是一个阻塞 会导致双方卡死

            # windows中 客户端 强行下线 服务器会抛出ConnectionResetError异常   来try处理
            # windows中 客户端 正常下线 会重复收到空消息

            # linux 客户端 强行下线 服务器会重复收到空消息
            # linux 客户端 正常下线 服务器也会重复收到空消息
            # 结论:既要处理异常 又要加上空消息的判断 保证服务器不会被终止或死循环
  
改进版服务器
import socket
c=socket.socket()
c.connect(('127.0.0.1',8888))



while True:
    msg=input('>>>:(q.退出)')
    if msg=='q':
        break
    elif not msg:
        continue
    # 发送数据
    c.send(msg.encode('utf-8'))
    # 接收服务器返回的数据
    data=c.recv(1024)
    print(data)
改进版客户端

 

posted @ 2019-02-28 18:39  777ijBGly-  阅读(159)  评论(0编辑  收藏  举报